Re: Thread programming

Justin Hopper wrote:

On Tue, 2003-06-17 at 10:23, Tristan Van Berkom wrote:
Justin Hopper wrote:

On Tue, 2003-06-17 at 06:01, Tristan Van Berkom wrote:

I've read the FAQ on thread programming, but I must be missing something
fundamental on how they work.

Any help is greatly appreciated.

Thread lockups are generally one thread stuck on a lock that's owned
either by another thread or that was locked earlier by the same

One thing I should mention is that I only have one thread running in the
background.  I assume the GUI runs in it's own thread, so that would
make a total of two threads. I'm not doing anything in the GUI when it locks up, but perhaps it is have trouble just reading the label that was
updated in the background thread.  I should also mention that the
background thread never locks up either, it keeps trucking along.

Can anyone confirm whether or not doing simple thread programming will
work while using libglade?

When Havoc said he didnt think libglade was "thread-safe"; I dont know if he meant the run time utility or the code that it generates. It is probable that glade doesn't generate code with mutex locks on object access et cetera et cetera but other than that, If you use glade to generate/parse an XML widget layout;
the job is quite simple.

- Use the glade_xml_get_widget(xml, "name") API
- Make _SURE_ that this is done in the same thread that you will access the "created objects" - Use threads to do lengthly background jobs and dont update any GUI memory space objects from that thread. (i.e. if you do a db query that returns 10
elements every `n' millies; pass those
to the gui thread to update your "listview" or whatnot; dont update directly). - If you use "sources" in your thread (i.e. g_timeout_add), make sure that your thread has its own
GMainLoop running.

If you follow this strict practice, I garauntee it will work. (well, it works for me ;-) ) There have been a bunch of extra stuff added to make thread programming in gtk more solid et cetera since "gtk+-2.x" (i.e. gdk_threads_enter/leave) which allow you
to do even cooler stuff.

Note. gdk_threads_enter/leave are by no means nescisary if you follow the above prectice. (I'm guessing that this is just a wrapper for some global mutex for the "drawing kit").

Also ofcourse I have to agree with Havoc about the backtrace;
may I recommend Valgrind ? it will tell you where and when a posix mutex
gets locked _or_ unlocked twice by the same thread (I though that was
pretty neat).


Thanks, Tristan (et al.). This seems like a very logical approach. Just as a side note, I tried debugging the application with gdb, but it
only showed:

[New Thread 1080082400 (LWP 28716)]
[New Thread 1090956592 (LWP 28717)]

So, I would probably have to use something like Valgrind to see where
the collision is occuring.

However, I'd rather pursue the idea of sending a message to the main
thread to update the GUI, and have all GUI updates done through that. Now my question is obvious: how do I notify the main loop? I saw a few
examples of gtk_signal_emit_*, but where do I catch these signals in the
gtk_main loop and update certain things?  Just to make sure I've given
the right background information:

// main.c
pthread_create(&check_tid, NULL, check_queues, window1);
gtk_main ();

The thread that is spun off will have data that needs to be passed to
the main loop for the GUI.  Using this method, do I need to enter and
leave threads in main.c or in the check_queues function?

Thanks again for all the help.

=== <snip from gdk_threads_enter doc> ==========
This macro marks the beginning of a critical section in which GDK and GTK+ functions can be called. Only one thread at a time can be in such a critial section.
==========< end snip >====================

I dont know if putting your gtk_main() inside a locked `gdk_threads_mutex' is common practice or something like that but AFAIK, its useless if you dont plan on updating the gui from more than one thread; and even then, you wouldnt put your entire gtk_main

As for communication; you could do that a number of ways :-)

This could work,

- Create a GQueue and a GMutex to handle the queue.
- in your main (GUI updating) thread, create a g_timeout_add
function and every once and a while, come and check the queue like so
/* process data in queue */

- in your child thread; when you have ready data; lock your mutex,
add data to the queue and unlock mutex.

It would usualy be nicer to be "event based" and use the GCond API but
that would defeat the purpose (putting the GUI thread to sleep *doh*). This
polling method should keep the GUI responsive.

Actualy, (*doh*) you could make a socket or a named pipe and write from the
child and read in the parent. This way you avoid dumb polling.
(why did I sugest that ?)


One thing I still don't understand: I only have one thread created, and
it just updates the text of some labels.  So, this thread is not
colliding with any other threads I've created, but perhaps is colliding
with the gtk_main() thread.  So basically, my check_queues thread is the
only thread that is making updates to the GUI, unless the gtk_main()
thread is trying to make updates to the widgets as well.

So creating a socket or named pipe would not seem to help me currently,
or creating another thread that just does GUI updates, as that is
basically all my current thread does.

I'm starting to think that I the gtk_main() thread is getting locked out
of reading/updating the widgets and that I just need to somehow get a
lock on these labels before I update them in the check_queues thread.  A
mutex would work great, except how would I get the gtk_main() thread to
even be aware of the mutex and use it.

Perhaps I'm going about this all wrong?

Ok, where did we start out.


pthread_create(&check_tid, NULL, check_queues, window1);
... gdk_threads_enter();
gtk_main ();

// check_queues.c
 while (1) {
        ...(check some mysql database for data)...
        label = lookup_widget(GTK_WIDGET(toplevel),"label_name");
        gtk_label_set_text(GTK_LABEL(label), "whatever");

I'm afraid this code _obviously_ locks up before you call gtk_main()
unless the freak occurence that your testing (1) in your while statement
at the same time.

gdk_threads_enter/leave are a mutex lock around a critical section. (can I be
more clear ?)

FORGET gdk_threads_enter/leave!

void main() {

g_io_channel_unix_somethingorother_new(hook to a pipe or socket or something
                                        to call, label_update_function);
pthread_create(&check_tid, NULL, check_queues, window1);
... gtk_main ();


label_update_function() {
 read(socket_fd, updated stuff from database);
 label = lookup_widget(GTK_WIDGET(toplevel),"label_name");
 gtk_label_set_text(GTK_LABEL(label), "whatever");

// check_queues.c

 while (mysql condition maybe ?) {
        ...(check some mysql database for data)...
        write(socket_fd, the data that should go on the label);

I think we're suffering from a lack of proper communication.

I very much hope that this is clear to you now :-)

Cheers all!,
I think the body of this thread might be getting out of control.  I'm
tempted to clear it, but the mailing list etiquette cops will hunt me
down and destroy me.....

OK, I now fully understand, and thank you for posting that bit from the
threads doc, that entering and leaving threads is not going to be needed
in my app.

What I still don't understand: where is the collision occurring?
If I base myself on your original code; your main executions space locks a mutex
that will only unlock when `gtk_main_quit()' gets called and your db query
thread will only execute then. (or it may have done exactly one itteration
before `gtk_main()')

If I only have one thread, and only that thread is making updates to the GUI,
why does the GUI itself (and I assume the gtk_main() thread), lock up?

what is `one thread' ? once you `pthread_create' ; you have two, do you not ?
who cares. lets say you have "two executions spaces"; that works.

the `void main() {}' execution space; the one that has the gtk_main() in it should
update the gui. if you want to update the gui from a child execution space;
put the gtk_main() in the child instead.

In other words, as long as the functions you write that update the gui are
marshalled by the GMainloop in gtk_main() (i.e. run in the same space),
you shouldn't have any race conditions.

I think until I have an answer to this, I won't understand how any code
rework will help, as they should all run into the same problem of making
updates to the GUI and then having the GUI lock up.

Thanks for everyone's patience.

Bah, I always take an hour or so reading/writing lists, it puts
variety in the day and keeps the technolagies fresh in my head.


 someone threw `GAsynchQueue' in the mix, you should read up,
its a good idea. (I'll use that next time).
The app works correctly now.  I changed the code to the following, just
to see if the idea would work:

// main.c
pthread_create(&check_tid, NULL, run_main, NULL);

// that's the end, no entering or leaving threads

// run_main thread function

// check_queues.c
while (loop)
 ...(check databases for info)...
 label = lookup_widget(GTK_WIDGET(toplevel),"label_whatever");
 gtk_label_set_text(GTK_LABEL(label), rtq->tickets_new);

You may have race conditions here (or you DO have race conditions here).
what happens when the area of your label is marked "dirty" and is being
redrawn at the same time as your other thread is performing a "gtk_label_set_text" ?

this is why you want to use a GAsynchQueue or a GIOChannel or something for
your child thread to tell mister "gtk_main()" thread _instead_ of calling
gtk_label_set_text directly. (why does it seem so complicated to say that you should
update the GUI in the SAME thread that gtk_main() is running in ?)

Ok, last question, and I really have learned a lot from all of this:

How do I make updates to the GUI from the same thread that gtk_main() is
run from, since that thread gets tied up as soon as gtk_main() gets
called?  I'm sure I'm being stupid here and I'm missing something
fundamental, but I understand that I should be making all GUI updates
from the same thread as the gtk_main() thread, to avoid lockups and race
conditions, but I'm just not seeing how to do that.

I should be set after this.
I was actually waiting for you to ask that question ;-)

   I guess this is your first experience with gtk, gtk programming generaly
isn't "proceedural" programming in the sence that the main loop driving your
proceedure is hidden inside the GMainLoop (in gtk_main()). Generaly you hook some callbacks to some widgets or timers or file descriptors (all of which can
be viewed as "sources"). In my previous pseudo code example; I sugested
that before you call `gtk_main()' you call `g-io-channel-unix-new()' on a socket
or named pipe and then call `g_io_add_watch()' so you have a GIOFunc that
will be called every time there is data on the file descriptor (you can have as many of theese watches as you want; the `select()' or `poll()' call is hidden
deep in glib.

(this way ofcourse you would feed information through your socket from the
child thread)


BUT!! I think it is to your advantage to use the GAsynchQueue:
(read up and understand)
since this api is made for _exactly_ this purpose, I would prefer it.
(for the purpose of communicating between threads).


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