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
g_signal_connect (window, "destroy", G_CALLBACK (destroy), NULL);
217
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
220
label = gtk_label_new ("And now for something completely different ...");
221
gtk_container_add (GTK_CONTAINER (window), label);
223
/* show everything */
224
gtk_widget_show (label);
225
gtk_widget_show (window);
227
/* create the threads */
228
yes_args.label = label;
229
yes_args.what = YES_IT_IS;
230
pthread_create (&yes_tid, NULL, argument_thread, &yes_args);
232
no_args.label = label;
233
no_args.what = NO_IT_IS_NOT;
234
pthread_create (&no_tid, NULL, argument_thread, &no_args);
236
/* enter the GTK main loop */
238
gdk_threads_leave (<!-- -->);
245
<!-- ##### SECTION See_Also ##### -->
250
<!-- ##### SECTION Stability_Level ##### -->
253
<!-- ##### SECTION Image ##### -->
256
<!-- ##### MACRO GDK_THREADS_ENTER ##### -->
258
This macro marks the beginning of a critical section in which GDK and
259
GTK+ functions can be called safely and without causing race
260
conditions. Only one thread at a time can be in such a critial
261
section. The macro expands to a no-op if #G_THREADS_ENABLED has not
262
been defined. Typically gdk_threads_enter() should be used instead of
268
<!-- ##### MACRO GDK_THREADS_LEAVE ##### -->
270
This macro marks the end of a critical section
271
begun with #GDK_THREADS_ENTER.
276
<!-- ##### FUNCTION gdk_threads_init ##### -->
284
<!-- ##### FUNCTION gdk_threads_enter ##### -->
286
This macro marks the beginning of a critical section in which GDK and
287
GTK+ functions can be called safely and without causing race
288
conditions. Only one thread at a time can be in such a critial
295
<!-- ##### FUNCTION gdk_threads_leave ##### -->
297
Leaves a critical region begun with gdk_threads_enter().
303
<!-- ##### VARIABLE gdk_threads_mutex ##### -->
305
The #GMutex used to implement the critical region for
306
gdk_threads_enter()/gdk_threads_leave().
310
<!-- ##### FUNCTION gdk_threads_set_lock_functions ##### -->
319
<!-- ##### FUNCTION gdk_threads_add_idle ##### -->
329
<!-- ##### FUNCTION gdk_threads_add_idle_full ##### -->
341
<!-- ##### FUNCTION gdk_threads_add_timeout ##### -->
352
<!-- ##### FUNCTION gdk_threads_add_timeout_full ##### -->
365
<!-- ##### FUNCTION gdk_threads_add_timeout_seconds ##### -->
376
<!-- ##### FUNCTION gdk_threads_add_timeout_seconds_full ##### -->