Re: Re: How to create a dialog window from a thread?



On 14 Nov 2000, at 21:45, Havoc Pennington wrote:


"Michael Loft" <michael loft dk> writes:
I'm writing a communications application, where I have a thread
listening to the serial port. When data arrives, I want the thread
to create a dialog window, so the user can decide what to do. The
problem is, that when I create the dialog, I only see the frame, and
gtk hangs. The thread continues to run.

Any suggestions on how to create the dialog would be most 
welcome. I've spent three whole days trying to do this until now.


Are you following the thread rules described in the FAQ at
www.gtk.org/faq?

Havoc


I think so, I'm doing the g_threads_enter() and g_threads_leave() 
stuff.

the code I'm, having trouble with looks like this:

/*
This is part of the header
*/

#include <gtk/gtk.h>
#include <pthread.h>

//...other stuff...//

/*
Functions that allow multitasking and event handling
*/
#ifndef G_THREADS_IMPL_POSIX
#define G_THREADS_IMPL_POSIX
#endif

pthread_t uart_listener;
                                                //This thread listens to the serial port
                                                //and runs when program is in slave mode.

GMutex *serial_mutex;
                                                //Mutex that is to prevent different threads
                                                //reading and writing to the serial port
                                                //at the same time.

void *checkForMessages (void *ptr);     
                                                //Function running in uart_listener thread

pthread_t ser_port_message_handler;
GCond *ser_port_message_recieved;       
                                                //Signal holder. Is signalled when a new 
                                                //message has been recieved from the 
                                                //serial port.

GMutex *ser_port_message_mutex;         
                                                //Mutex prevents reading and writing the 
                                                //message simultainously.

typedef struct {
        byte messagetype;
        int datalength;
        byte *data;
}message;                               //Message structure.

message ser_port_message;               
                                                //This is the message holder.

void *serPortMessageHandler (void *ptr);
                                                //Function waits for a message from             
                                                //the port, and then takes action.

static guint signal_show_message_dialog;
                                                //Id of my signal

void sletmigsenere ();
                                                //Dialog function


/*
This is my main loop
*/

int main (int argc, char *argv[])
{
        g_thread_init(NULL);
        gtk_init (&argc, &argv);
        g_print("Starting Main() \n");  

        serial_mutex = g_mutex_new();
        ser_port_message_recieved = g_cond_new();
        ser_port_message_mutex = g_mutex_new();
                
        showStartupDialog();                    //This works fine.
                                                                        //Used for choosing the serial  
                                                                        //port and master/slave mode
        
        gdk_threads_enter();
        pthread_create (&ser_port_message_handler, NULL,
                                &serPortMessageHandler, NULL);
        gtk_main ();
        gdk_threads_leave();

        g_mutex_free (serial_mutex);
        g_mutex_free (ser_port_message_mutex);
        return(0);
}

/*
The following is done in the function that creates the main window.
I have a global pointer p, that points to an instance of a structure 
containing information on if the program is in slave mode or master 
mode, as well as a pointer to the main window. This information 
has been set previously.
*/

/*
Add the >signal_show_message_dialog< signal to the main window
*/
        signal_show_message_dialog =    
                        gtk_object_class_user_signal_new (
                                GTK_OBJECT_CLASS (gtk_type_class 
                                (GTK_TYPE_WINDOW)),
                                "signal_show_message_dialog",
                                GTK_RUN_FIRST,
                                gtk_signal_default_marshaller,
                                GTK_TYPE_NONE,
                                0);

/*
Connect a >show_message_dialog< signal to the sletmigsenere 
function.
This signal is emitted to the main window by the 
serPortMessageHandler function.
*/
        gtk_signal_connect (GTK_OBJECT (p->window),
                                                 "signal_show_message_dialog",
                                                GTK_SIGNAL_FUNC (sletmigsenere), p);

//if in slave mode then make idle function that checks for
// messages     
        if(!(p->master))
        {
                pthread_create (&uart_listener, NULL,
                                &checkForMessages, NULL);

        }


/*
This is my >check for messages< thread.
The serial io is done in the serialport instance of a serial 
communications class, class TestMasterSlaveComm {...}.
I'm doing this in M$ Windows, so I can't just read from a file.
The win32api calls is put in the TestMasterSlaveComm class only.
*/

void *checkForMessages(void *ptr)
{
        byte messagetype;
        int datalength;
        byte *data;
        bool succes;
        
/*
Listen to the port
*/

        while (TRUE)
        {
                        
        if(!(serialport->isConnected())) 
        {       //We have to connect first
                g_mutex_lock (serial_mutex);    //Lock serial port
                serialport->connect();
                g_mutex_unlock (serial_mutex);  //Release serial port
                g_print("Sleeping\n");
                g_usleep(1000000);              //Sleep 1 second
                
        }
        
        g_mutex_lock (serial_mutex);            //Lock serial port
        succes = serialport->readMessage (&messagetype,
                                                                         &datalength, &data);
        g_mutex_unlock (serial_mutex);          //Release serial port
                
        if (succes)
        {
                /*
                Write the message to the global variable and then signal the
                serPortMessageHandler.
                */
                g_mutex_lock (ser_port_message_mutex);
                ser_port_message.messagetype = messagetype;
                ser_port_message.datalength = datalength;
                ser_port_message.data = data;
                g_mutex_unlock (ser_port_message_mutex);
                g_cond_signal (ser_port_message_recieved);
        }

        g_print("Sleeping\n");
        g_usleep(1000000);                      //Sleep 1 second
        }
        
}


/*
The message handler looks like this:
*/
void *serPortMessageHandler (void *ptr)
{
        byte messagetype;
        int datalength;
        byte *data;

        g_mutex_lock (ser_port_message_mutex);  
                                                //Lock the mutex at first entry, 
                                                //so the wait function works as
                                                //expected.

        while (TRUE)
        {
                g_cond_wait (ser_port_message_recieved,
                                                 ser_port_message_mutex);
                                                        //Wait for a message
        
        messagetype = ser_port_message.messagetype;
        datalength = ser_port_message.datalength;
        data = ser_port_message.data;
        
                switch (messagetype) 
                {
                        /*
                        Here goes different checks for correct message types, 
                        etc. Then the signal is emitted. rtu.window is the main 
                        window
                        */

                        case correctMessage : 
                        gtk_signal_emit_by_name (GTK_OBJECT (rtu.window),
                                        "signal_show_message_dialog",
                                        NULL);
                                break;
                        }

                        default :
                        {
                        
                        }
        
                } //end switch
        } //end while
}

/*
And finally, this is the dialog creation.
*/

void sletossemaj (GtkWidget *widget, GMainLoop *loop)
{
        g_main_quit(loop);
}

void sletmigsenere ()
{
        GMainLoop *localloop = g_main_new (FALSE);

        GtkWidget *dialog, *label, *okay_button;

        /* Create the widgets */
        dialog = gtk_dialog_new();
        label = gtk_label_new ("Aloha!");
        okay_button = gtk_button_new_with_label("Okay");

        /* Ensure that the dialog box is destroyed when the user clicks 
        ok. */
        gtk_signal_connect (GTK_OBJECT (okay_button), "clicked",
                      GTK_SIGNAL_FUNC (sletossemaj), localloop);

        gtk_container_add (GTK_CONTAINER (
                        GTK_DIALOG(dialog)->action_area),
                        okay_button);

        /* Add the label, and show everything we've added to the dialog. 
*/
        gtk_container_add (GTK_CONTAINER (
                                GTK_DIALOG(dialog)->vbox),
                                label);

        gtk_widget_show (label);
        gtk_widget_show (okay_button);

        gtk_widget_show (dialog);
        g_main_run(localloop);
        g_main_destroy(localloop);
        gtk_widget_destroy (dialog);
}

----------------

Since yesterday, I added the part where I use a new GMainLoop to 
show the dialog.
This is actually working now, but I get tons of warnings:

GLib-WARNING **: g_main_iterate() : main loop already active in 
another thread

So I must be doing something wrong :-(

Why is it a different thread, that runs the gtk_main() loop, when the 
dialog window is popped up by signalling to the main window?


WOW, that was a lot, hope some of you can help me on this one.

- Michael Loft




[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]