]> Pileus Git - ~andy/gtk/blob - docs/reference/gdk/tmpl/threads.sgml
2.13.6
[~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   gtk_signal_connect (GTK_OBJECT (window), "destroy",
216                       GTK_SIGNAL_FUNC (destroy), NULL);
217
218   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
219
220   /* create a label */
221   label = gtk_label_new ("And now for something completely different ...");
222   gtk_container_add (GTK_CONTAINER (window), label);
223   
224   /* show everything */
225   gtk_widget_show (label);
226   gtk_widget_show (window);
227
228   /* create the threads */
229   yes_args.label = label;
230   yes_args.what = YES_IT_IS;
231   pthread_create (&amp;yes_tid, NULL, argument_thread, &amp;yes_args);
232
233   no_args.label = label;
234   no_args.what = NO_IT_IS_NOT;
235   pthread_create (&amp;no_tid, NULL, argument_thread, &amp;no_args);
236
237   /* enter the GTK main loop */
238   gtk_main (<!-- -->);
239   gdk_threads_leave (<!-- -->);
240
241   return 0;
242 }
243 </programlisting>
244 </informalexample>
245
246 <!-- ##### SECTION See_Also ##### -->
247 <para>
248
249 </para>
250
251 <!-- ##### SECTION Stability_Level ##### -->
252
253
254 <!-- ##### MACRO GDK_THREADS_ENTER ##### -->
255 <para>
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
261 this macro.
262 </para>
263
264
265
266 <!-- ##### MACRO GDK_THREADS_LEAVE ##### -->
267 <para>
268 This macro marks the end of a critical section 
269 begun with #GDK_THREADS_ENTER.
270 </para>
271
272
273
274 <!-- ##### FUNCTION gdk_threads_init ##### -->
275 <para>
276
277 </para>
278
279
280
281 <!-- ##### FUNCTION gdk_threads_enter ##### -->
282 <para>
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
286 section.
287 </para>
288
289
290
291 <!-- ##### FUNCTION gdk_threads_leave ##### -->
292 <para>
293 Leaves a critical region begun with gdk_threads_enter(). 
294 </para>
295
296
297
298 <!-- ##### VARIABLE gdk_threads_mutex ##### -->
299 <para>
300 The #GMutex used to implement the critical region for
301 gdk_threads_enter()/gdk_threads_leave(). 
302 </para>
303
304
305 <!-- ##### FUNCTION gdk_threads_set_lock_functions ##### -->
306 <para>
307
308 </para>
309
310 @enter_fn: 
311 @leave_fn: 
312
313
314 <!-- ##### FUNCTION gdk_threads_add_idle ##### -->
315 <para>
316
317 </para>
318
319 @function: 
320 @data: 
321 @Returns: 
322
323
324 <!-- ##### FUNCTION gdk_threads_add_idle_full ##### -->
325 <para>
326
327 </para>
328
329 @priority: 
330 @function: 
331 @data: 
332 @notify: 
333 @Returns: 
334
335
336 <!-- ##### FUNCTION gdk_threads_add_timeout ##### -->
337 <para>
338
339 </para>
340
341 @interval: 
342 @function: 
343 @data: 
344 @Returns: 
345
346
347 <!-- ##### FUNCTION gdk_threads_add_timeout_full ##### -->
348 <para>
349
350 </para>
351
352 @priority: 
353 @interval: 
354 @function: 
355 @data: 
356 @notify: 
357 @Returns: 
358
359
360 <!-- ##### FUNCTION gdk_threads_add_timeout_seconds ##### -->
361 <para>
362
363 </para>
364
365 @interval: 
366 @function: 
367 @data: 
368 @Returns: 
369
370
371 <!-- ##### FUNCTION gdk_threads_add_timeout_seconds_full ##### -->
372 <para>
373
374 </para>
375
376 @priority: 
377 @interval: 
378 @function: 
379 @data: 
380 @notify: 
381 @Returns: 
382
383