]> Pileus Git - ~andy/gtk/blob - docs/reference/gdk/tmpl/threads.sgml
Make 3.0 parallel-installable to 2.x
[~andy/gtk] / docs / reference / gdk / tmpl / threads.sgml
1 <!-- ##### SECTION Title ##### -->
2 Threads
3
4 <!-- ##### SECTION Short_Description ##### -->
5 Functions for using GDK in multi-threaded programs
6
7 <!-- ##### SECTION Long_Description ##### -->
8 <para>
9 For thread safety, GDK relies on the thread primitives in GLib, 
10 and on the thread-safe GLib main loop.
11 </para>
12 <para>
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.
17 </para>
18 <para>
19 GTK+ is "thread aware" but not thread safe &mdash; 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+ 
22 at any given time.
23 </para>
24 <para>
25 Unfortunately the above holds with the X11 backend only. With the
26 Win32 backend, GDK calls should not be attempted from multiple threads
27 at all.
28 </para>
29 <para>
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.
32 </para>
33 <para>
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.
42 </para>
43 <para>
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.
47 </para>
48 <para>
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.
51 </para>
52
53 <para>
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.)
61 </para>
62
63 <para>A minimal main program for a threaded GTK+ application
64 looks like:</para>
65
66 <informalexample>
67 <programlisting role="C">
68 int
69 main (int argc, char *argv[])
70 {
71   GtkWidget *window;
72
73   g_thread_init (NULL);
74   gdk_threads_init (<!-- -->);
75   gdk_threads_enter (<!-- -->);
76
77   gtk_init (&amp;argc, &amp;argv);
78
79   window = create_window (<!-- -->);
80   gtk_widget_show (window);
81
82   gtk_main (<!-- -->);
83   gdk_threads_leave (<!-- -->);
84
85   return 0;
86 }
87 </programlisting>
88 </informalexample>
89
90 <para>
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
96 do.
97 </para>
98
99 <para>Erik Mouw contributed the following code example to
100 illustrate how to use threads within GTK+ programs.
101 </para>
102
103 <informalexample>
104 <programlisting role="C">
105 /*-------------------------------------------------------------------------
106  * Filename:      gtk-thread.c
107  * Version:       0.99.1
108  * Copyright:     Copyright (C) 1999, Erik Mouw
109  * Author:        Erik Mouw &lt;J.A.K.Mouw@its.tudelft.nl&gt;
110  * Description:   GTK threads example. 
111  * Created at:    Sun Oct 17 21:27:09 1999
112  * Modified by:   Erik Mouw &lt;J.A.K.Mouw@its.tudelft.nl&gt;
113  * Modified at:   Sun Oct 24 17:21:41 1999
114  *-----------------------------------------------------------------------*/
115 /*
116  * Compile with:
117  *
118  * cc -o gtk-thread gtk-thread.c `gtk-config --cflags --libs gthread`
119  *
120  * Thanks to Sebastian Wilhelmi and Owen Taylor for pointing out some
121  * bugs.
122  *
123  */
124
125 &num;include &lt;stdio.h&gt;
126 &num;include &lt;stdlib.h&gt;
127 &num;include &lt;unistd.h&gt;
128 &num;include &lt;time.h&gt;
129 &num;include &lt;gtk/gtk.h&gt;
130 &num;include &lt;glib.h&gt;
131 &num;include &lt;pthread.h&gt;
132
133 &num;define YES_IT_IS    (1)
134 &num;define NO_IT_IS_NOT (0)
135
136 typedef struct 
137 {
138   GtkWidget *label;
139   int what;
140 } yes_or_no_args;
141
142 G_LOCK_DEFINE_STATIC (yes_or_no);
143 static volatile int yes_or_no = YES_IT_IS;
144
145 void destroy (GtkWidget *widget, gpointer data)
146 {
147   gtk_main_quit (<!-- -->);
148 }
149
150 void *argument_thread (void *args)
151 {
152   yes_or_no_args *data = (yes_or_no_args *)args;
153   gboolean say_something;
154
155   for (;;)
156     {
157       /* sleep a while */
158       sleep(rand(<!-- -->) / (RAND_MAX / 3) + 1);
159
160       /* lock the yes_or_no_variable */
161       G_LOCK(yes_or_no);
162
163       /* do we have to say something? */
164       say_something = (yes_or_no != data->what);
165
166       if(say_something)
167         {
168           /* set the variable */
169           yes_or_no = data->what;
170         }
171
172       /* Unlock the yes_or_no variable */
173       G_UNLOCK (yes_or_no);
174
175       if (say_something)
176         {
177           /* get GTK thread lock */
178           gdk_threads_enter (<!-- -->);
179
180           /* set label text */
181           if(data->what == YES_IT_IS)
182             gtk_label_set_text (GTK_LABEL (data->label), "O yes, it is!");
183           else
184             gtk_label_set_text (GTK_LABEL (data->label), "O no, it isn't!");
185
186           /* release GTK thread lock */
187           gdk_threads_leave (<!-- -->);
188         }
189     }
190
191   return NULL;
192 }
193
194 int main (int argc, char *argv[])
195 {
196   GtkWidget *window;
197   GtkWidget *label;
198   yes_or_no_args yes_args, no_args;
199   pthread_t no_tid, yes_tid;
200
201   /* init threads */
202   g_thread_init (NULL);
203   gdk_threads_init (<!-- -->);
204   gdk_threads_enter (<!-- -->);
205
206   /* init gtk */
207   gtk_init(&amp;argc, &amp;argv);
208
209   /* init random number generator */
210   srand ((unsigned int) time (NULL));
211
212   /* create a window */
213   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
214
215   g_signal_connect (window, "destroy", G_CALLBACK (destroy), NULL);
216
217   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
218
219   /* create a label */
220   label = gtk_label_new ("And now for something completely different ...");
221   gtk_container_add (GTK_CONTAINER (window), label);
222   
223   /* show everything */
224   gtk_widget_show (label);
225   gtk_widget_show (window);
226
227   /* create the threads */
228   yes_args.label = label;
229   yes_args.what = YES_IT_IS;
230   pthread_create (&amp;yes_tid, NULL, argument_thread, &amp;yes_args);
231
232   no_args.label = label;
233   no_args.what = NO_IT_IS_NOT;
234   pthread_create (&amp;no_tid, NULL, argument_thread, &amp;no_args);
235
236   /* enter the GTK main loop */
237   gtk_main (<!-- -->);
238   gdk_threads_leave (<!-- -->);
239
240   return 0;
241 }
242 </programlisting>
243 </informalexample>
244
245 <!-- ##### SECTION See_Also ##### -->
246 <para>
247
248 </para>
249
250 <!-- ##### SECTION Stability_Level ##### -->
251
252
253 <!-- ##### SECTION Image ##### -->
254
255
256 <!-- ##### MACRO GDK_THREADS_ENTER ##### -->
257 <para>
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
263 this macro.
264 </para>
265
266
267
268 <!-- ##### MACRO GDK_THREADS_LEAVE ##### -->
269 <para>
270 This macro marks the end of a critical section 
271 begun with #GDK_THREADS_ENTER.
272 </para>
273
274
275
276 <!-- ##### FUNCTION gdk_threads_init ##### -->
277 <para>
278
279 </para>
280
281 @void: 
282
283
284 <!-- ##### FUNCTION gdk_threads_enter ##### -->
285 <para>
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
289 section.
290 </para>
291
292 @void: 
293
294
295 <!-- ##### FUNCTION gdk_threads_leave ##### -->
296 <para>
297 Leaves a critical region begun with gdk_threads_enter(). 
298 </para>
299
300 @void: 
301
302
303 <!-- ##### VARIABLE gdk_threads_mutex ##### -->
304 <para>
305 The #GMutex used to implement the critical region for
306 gdk_threads_enter()/gdk_threads_leave(). 
307 </para>
308
309
310 <!-- ##### FUNCTION gdk_threads_set_lock_functions ##### -->
311 <para>
312
313 </para>
314
315 @enter_fn: 
316 @leave_fn: 
317
318
319 <!-- ##### FUNCTION gdk_threads_add_idle ##### -->
320 <para>
321
322 </para>
323
324 @function: 
325 @data: 
326 @Returns: 
327
328
329 <!-- ##### FUNCTION gdk_threads_add_idle_full ##### -->
330 <para>
331
332 </para>
333
334 @priority: 
335 @function: 
336 @data: 
337 @notify: 
338 @Returns: 
339
340
341 <!-- ##### FUNCTION gdk_threads_add_timeout ##### -->
342 <para>
343
344 </para>
345
346 @interval: 
347 @function: 
348 @data: 
349 @Returns: 
350
351
352 <!-- ##### FUNCTION gdk_threads_add_timeout_full ##### -->
353 <para>
354
355 </para>
356
357 @priority: 
358 @interval: 
359 @function: 
360 @data: 
361 @notify: 
362 @Returns: 
363
364
365 <!-- ##### FUNCTION gdk_threads_add_timeout_seconds ##### -->
366 <para>
367
368 </para>
369
370 @interval: 
371 @function: 
372 @data: 
373 @Returns: 
374
375
376 <!-- ##### FUNCTION gdk_threads_add_timeout_seconds_full ##### -->
377 <para>
378
379 </para>
380
381 @priority: 
382 @interval: 
383 @function: 
384 @data: 
385 @notify: 
386 @Returns: 
387
388