1 <!-- ##### SECTION Title ##### -->
4 <!-- ##### SECTION Short_Description ##### -->
5 Functions for using GDK in multi-threaded programs
7 <!-- ##### SECTION Long_Description ##### -->
9 For thread safety, GDK relies on the thread primitives in GLib,
10 and on the thread-safe GLib main loop.
13 GLib is completely thread safe (all global data is automatically
14 locked), but individual data structure instances are not automatically
15 locked for performance reasons. So e.g. you must coordinate
16 accesses to the same #GHashTable from multiple threads.
19 GTK+ is "thread aware" but not thread safe — it provides a
20 global lock controlled by gdk_threads_enter()/gdk_threads_leave()
21 which protects all use of GTK+. That is, only one thread can use GTK+
25 Unfortunately the above holds with the X11 backend only. With the
26 Win32 backend, GDK calls should not be attempted from multiple threads
30 You must call g_thread_init() and gdk_threads_init() before executing
31 any other GTK+ or GDK functions in a threaded GTK+ program.
34 Idles, timeouts, and input functions from GLib, such as g_idle_add(), are
35 executed outside of the main GTK+ lock.
36 So, if you need to call GTK+ inside of such a callback, you must surround
37 the callback with a gdk_threads_enter()/gdk_threads_leave() pair or use
38 gdk_threads_add_idle_full() which does this for you.
39 However, event dispatching from the mainloop is still executed within
40 the main GTK+ lock, so callback functions connected to event signals
41 like GtkWidget::button-press-event, do not need thread protection.
44 In particular, this means, if you are writing widgets that might
45 be used in threaded programs, you <emphasis>must</emphasis> surround
46 timeouts and idle functions in this matter.
49 As always, you must also surround any calls to GTK+ not made within
50 a signal handler with a gdk_threads_enter()/gdk_threads_leave() pair.
54 Before calling gdk_threads_leave() from a thread other
55 than your main thread, you probably want to call gdk_flush()
56 to send all pending commands to the windowing system.
57 (The reason you don't need to do this from the main thread
58 is that GDK always automatically flushes pending commands
59 when it runs out of incoming events to process and has
60 to sleep while waiting for more events.)
63 <para>A minimal main program for a threaded GTK+ application
67 <programlisting role="C">
69 main (int argc, char *argv[])
74 gdk_threads_init (<!-- -->);
75 gdk_threads_enter (<!-- -->);
77 gtk_init (&argc, &argv);
79 window = create_window (<!-- -->);
80 gtk_widget_show (window);
83 gdk_threads_leave (<!-- -->);
91 Callbacks require a bit of attention. Callbacks from GTK+ signals
92 are made within the GTK+ lock. However callbacks from GLib (timeouts,
93 IO callbacks, and idle functions) are made outside of the GTK+
94 lock. So, within a signal handler you do not need to call
95 gdk_threads_enter(), but within the other types of callbacks, you
99 <para>Erik Mouw contributed the following code example to
100 illustrate how to use threads within GTK+ programs.
104 <programlisting role="C">
105 /*-------------------------------------------------------------------------
106 * Filename: gtk-thread.c
108 * Copyright: Copyright (C) 1999, Erik Mouw
109 * Author: Erik Mouw <J.A.K.Mouw@its.tudelft.nl>
110 * Description: GTK threads example.
111 * Created at: Sun Oct 17 21:27:09 1999
112 * Modified by: Erik Mouw <J.A.K.Mouw@its.tudelft.nl>
113 * Modified at: Sun Oct 24 17:21:41 1999
114 *-----------------------------------------------------------------------*/
118 * cc -o gtk-thread gtk-thread.c `gtk-config --cflags --libs gthread`
120 * Thanks to Sebastian Wilhelmi and Owen Taylor for pointing out some
125 #include <stdio.h>
126 #include <stdlib.h>
127 #include <unistd.h>
128 #include <time.h>
129 #include <gtk/gtk.h>
130 #include <glib.h>
131 #include <pthread.h>
133 #define YES_IT_IS (1)
134 #define NO_IT_IS_NOT (0)
142 G_LOCK_DEFINE_STATIC (yes_or_no);
143 static volatile int yes_or_no = YES_IT_IS;
145 void destroy (GtkWidget *widget, gpointer data)
147 gtk_main_quit (<!-- -->);
150 void *argument_thread (void *args)
152 yes_or_no_args *data = (yes_or_no_args *)args;
153 gboolean say_something;
158 sleep(rand(<!-- -->) / (RAND_MAX / 3) + 1);
160 /* lock the yes_or_no_variable */
163 /* do we have to say something? */
164 say_something = (yes_or_no != data->what);
168 /* set the variable */
169 yes_or_no = data->what;
172 /* Unlock the yes_or_no variable */
173 G_UNLOCK (yes_or_no);
177 /* get GTK thread lock */
178 gdk_threads_enter (<!-- -->);
181 if(data->what == YES_IT_IS)
182 gtk_label_set_text (GTK_LABEL (data->label), "O yes, it is!");
184 gtk_label_set_text (GTK_LABEL (data->label), "O no, it isn't!");
186 /* release GTK thread lock */
187 gdk_threads_leave (<!-- -->);
194 int main (int argc, char *argv[])
198 yes_or_no_args yes_args, no_args;
199 pthread_t no_tid, yes_tid;
202 g_thread_init (NULL);
203 gdk_threads_init (<!-- -->);
204 gdk_threads_enter (<!-- -->);
207 gtk_init(&argc, &argv);
209 /* init random number generator */
210 srand ((unsigned int) time (NULL));
212 /* create a window */
213 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
215 gtk_signal_connect (GTK_OBJECT (window), "destroy",
216 GTK_SIGNAL_FUNC (destroy), NULL);
218 gtk_container_set_border_width (GTK_CONTAINER (window), 10);
221 label = gtk_label_new ("And now for something completely different ...");
222 gtk_container_add (GTK_CONTAINER (window), label);
224 /* show everything */
225 gtk_widget_show (label);
226 gtk_widget_show (window);
228 /* create the threads */
229 yes_args.label = label;
230 yes_args.what = YES_IT_IS;
231 pthread_create (&yes_tid, NULL, argument_thread, &yes_args);
233 no_args.label = label;
234 no_args.what = NO_IT_IS_NOT;
235 pthread_create (&no_tid, NULL, argument_thread, &no_args);
237 /* enter the GTK main loop */
239 gdk_threads_leave (<!-- -->);
246 <!-- ##### SECTION See_Also ##### -->
251 <!-- ##### SECTION Stability_Level ##### -->
254 <!-- ##### MACRO GDK_THREADS_ENTER ##### -->
256 This macro marks the beginning of a critical section in which GDK and
257 GTK+ functions can be called safely and without causing race
258 conditions. Only one thread at a time can be in such a critial
259 section. The macro expands to a no-op if #G_THREADS_ENABLED has not
260 been defined. Typically gdk_threads_enter() should be used instead of
266 <!-- ##### MACRO GDK_THREADS_LEAVE ##### -->
268 This macro marks the end of a critical section
269 begun with #GDK_THREADS_ENTER.
274 <!-- ##### FUNCTION gdk_threads_init ##### -->
281 <!-- ##### FUNCTION gdk_threads_enter ##### -->
283 This macro marks the beginning of a critical section in which GDK and
284 GTK+ functions can be called safely and without causing race
285 conditions. Only one thread at a time can be in such a critial
291 <!-- ##### FUNCTION gdk_threads_leave ##### -->
293 Leaves a critical region begun with gdk_threads_enter().
298 <!-- ##### VARIABLE gdk_threads_mutex ##### -->
300 The #GMutex used to implement the critical region for
301 gdk_threads_enter()/gdk_threads_leave().
305 <!-- ##### FUNCTION gdk_threads_set_lock_functions ##### -->
314 <!-- ##### FUNCTION gdk_threads_add_idle ##### -->
324 <!-- ##### FUNCTION gdk_threads_add_idle_full ##### -->
336 <!-- ##### FUNCTION gdk_threads_add_timeout ##### -->
347 <!-- ##### FUNCTION gdk_threads_add_timeout_full ##### -->
360 <!-- ##### FUNCTION gdk_threads_add_timeout_seconds ##### -->
371 <!-- ##### FUNCTION gdk_threads_add_timeout_seconds_full ##### -->