Re: Re: How to create a dialog window from a thread?
- From: "Michael Loft" <michael loft dk>
- To: Havoc Pennington <hp redhat com>
- Cc: gtk-app-devel-list gnome org
- Subject: Re: Re: How to create a dialog window from a thread?
- Date: Wed, 15 Nov 2000 10:28:32 +0100
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]