]> Pileus Git - ~andy/gtk/blob - docs/reference/gdk/tmpl/threads.sgml
2.7.0
[~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 You must call g_thread_init() and gdk_threads_init() before executing
26 any other GTK+ or GDK functions in a threaded GTK+ program.
27 </para>
28 <para>
29 Idles, timeouts, and input functions are executed outside
30 of the main GTK+ lock. So, if you need to call GTK+
31 inside of such a callback, you must surround the callback
32 with a gdk_threads_enter()/gdk_threads_leave() pair.
33 (However, signals are still executed within the main
34 GTK+ lock.)
35 </para>
36 <para>
37 In particular, this means, if you are writing widgets that might 
38 be used in threaded programs, you <emphasis>must</emphasis> surround 
39 timeouts and idle functions in this matter.
40 </para>
41 <para>
42 As always, you must also surround any calls to GTK+ not made within 
43 a signal handler with a gdk_threads_enter()/gdk_threads_leave() pair.
44 </para>
45
46 <para>
47 Before calling gdk_threads_leave() from a thread other
48 than your main thread, you probably want to call gdk_flush()
49 to send all pending commands to the windowing system.
50 (The reason you don't need to do this from the main thread
51 is that GDK always automatically flushes pending commands
52 when it runs out of incoming events to process and has
53 to sleep while waiting for more events.)
54 </para>
55
56 <para>A minimal main program for a threaded GTK+ application
57 looks like:</para>
58
59 <informalexample>
60 <programlisting role="C">
61 int
62 main (int argc, char *argv[])
63 {
64   GtkWidget *window;
65
66   g_thread_init (NULL);
67   gdk_threads_init (<!-- -->);
68   gdk_threads_enter (<!-- -->);
69
70   gtk_init (&amp;argc, &amp;argv);
71
72   window = create_window (<!-- -->);
73   gtk_widget_show (window);
74
75   gtk_main (<!-- -->);
76   gdk_threads_leave (<!-- -->);
77
78   return 0;
79 }
80 </programlisting>
81 </informalexample>
82
83 <para>
84 Callbacks require a bit of attention. Callbacks from GTK+ signals
85 are made within the GTK+ lock. However callbacks from GLib (timeouts,
86 IO callbacks, and idle functions) are made outside of the GTK+
87 lock. So, within a signal handler you do not need to call
88 gdk_threads_enter(), but within the other types of callbacks, you
89 do.
90 </para>
91
92 <para>Erik Mouw contributed the following code example to
93 illustrate how to use threads within GTK+ programs.
94 </para>
95
96 <informalexample>
97 <programlisting role="C">
98 /*-------------------------------------------------------------------------
99  * Filename:      gtk-thread.c
100  * Version:       0.99.1
101  * Copyright:     Copyright (C) 1999, Erik Mouw
102  * Author:        Erik Mouw &lt;J.A.K.Mouw@its.tudelft.nl&gt;
103  * Description:   GTK threads example. 
104  * Created at:    Sun Oct 17 21:27:09 1999
105  * Modified by:   Erik Mouw &lt;J.A.K.Mouw@its.tudelft.nl&gt;
106  * Modified at:   Sun Oct 24 17:21:41 1999
107  *-----------------------------------------------------------------------*/
108 /*
109  * Compile with:
110  *
111  * cc -o gtk-thread gtk-thread.c `gtk-config --cflags --libs gthread`
112  *
113  * Thanks to Sebastian Wilhelmi and Owen Taylor for pointing out some
114  * bugs.
115  *
116  */
117
118 &num;include &lt;stdio.h&gt;
119 &num;include &lt;stdlib.h&gt;
120 &num;include &lt;unistd.h&gt;
121 &num;include &lt;time.h&gt;
122 &num;include &lt;gtk/gtk.h&gt;
123 &num;include &lt;glib.h&gt;
124 &num;include &lt;pthread.h&gt;
125
126 &num;define YES_IT_IS    (1)
127 &num;define NO_IT_IS_NOT (0)
128
129 typedef struct 
130 {
131   GtkWidget *label;
132   int what;
133 } yes_or_no_args;
134
135 G_LOCK_DEFINE_STATIC (yes_or_no);
136 static volatile int yes_or_no = YES_IT_IS;
137
138 void destroy (GtkWidget *widget, gpointer data)
139 {
140   gtk_main_quit (<!-- -->);
141 }
142
143 void *argument_thread (void *args)
144 {
145   yes_or_no_args *data = (yes_or_no_args *)args;
146   gboolean say_something;
147
148   for (;;)
149     {
150       /* sleep a while */
151       sleep(rand(<!-- -->) / (RAND_MAX / 3) + 1);
152
153       /* lock the yes_or_no_variable */
154       G_LOCK(yes_or_no);
155
156       /* do we have to say something? */
157       say_something = (yes_or_no != data->what);
158
159       if(say_something)
160         {
161           /* set the variable */
162           yes_or_no = data->what;
163         }
164
165       /* Unlock the yes_or_no variable */
166       G_UNLOCK (yes_or_no);
167
168       if (say_something)
169         {
170           /* get GTK thread lock */
171           gdk_threads_enter (<!-- -->);
172
173           /* set label text */
174           if(data->what == YES_IT_IS)
175             gtk_label_set_text (GTK_LABEL (data->label), "O yes, it is!");
176           else
177             gtk_label_set_text (GTK_LABEL (data->label), "O no, it isn't!");
178
179           /* release GTK thread lock */
180           gdk_threads_leave (<!-- -->);
181         }
182     }
183
184   return NULL;
185 }
186
187 int main (int argc, char *argv[])
188 {
189   GtkWidget *window;
190   GtkWidget *label;
191   yes_or_no_args yes_args, no_args;
192   pthread_t no_tid, yes_tid;
193
194   /* init threads */
195   g_thread_init (NULL);
196   gdk_threads_init (<!-- -->);
197   gdk_threads_enter (<!-- -->);
198
199   /* init gtk */
200   gtk_init(&amp;argc, &amp;argv);
201
202   /* init random number generator */
203   srand ((unsigned int) time (NULL));
204
205   /* create a window */
206   window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
207
208   gtk_signal_connect (GTK_OBJECT (window), "destroy",
209                       GTK_SIGNAL_FUNC (destroy), NULL);
210
211   gtk_container_set_border_width (GTK_CONTAINER (window), 10);
212
213   /* create a label */
214   label = gtk_label_new ("And now for something completely different ...");
215   gtk_container_add (GTK_CONTAINER (window), label);
216   
217   /* show everything */
218   gtk_widget_show (label);
219   gtk_widget_show (window);
220
221   /* create the threads */
222   yes_args.label = label;
223   yes_args.what = YES_IT_IS;
224   pthread_create (&amp;yes_tid, NULL, argument_thread, &amp;yes_args);
225
226   no_args.label = label;
227   no_args.what = NO_IT_IS_NOT;
228   pthread_create (&amp;no_tid, NULL, argument_thread, &amp;no_args);
229
230   /* enter the GTK main loop */
231   gtk_main (<!-- -->);
232   gdk_threads_leave (<!-- -->);
233
234   return 0;
235 }
236 </programlisting>
237 </informalexample>
238
239 <!-- ##### SECTION See_Also ##### -->
240 <para>
241
242 </para>
243
244 <!-- ##### SECTION Stability_Level ##### -->
245
246
247 <!-- ##### MACRO GDK_THREADS_ENTER ##### -->
248 <para>
249 This macro marks the beginning of a critical section in which GDK and GTK+
250 functions can be called.  Only one thread at a time can be in such a
251 critial section. The macro expands to a no-op if #G_THREADS_ENABLED
252 has not been defined. Typically gdk_threads_enter() should be used 
253 instead of this macro.
254 </para>
255
256
257
258 <!-- ##### MACRO GDK_THREADS_LEAVE ##### -->
259 <para>
260 This macro marks the end of a critical section 
261 begun with #GDK_THREADS_ENTER.
262 </para>
263
264
265
266 <!-- ##### FUNCTION gdk_threads_init ##### -->
267 <para>
268
269 </para>
270
271
272
273 <!-- ##### FUNCTION gdk_threads_enter ##### -->
274 <para>
275 This macro marks the beginning of a critical section
276 in which GDK and GTK+ functions can be called.
277 Only one thread at a time can be in such a critial 
278 section.
279 </para>
280
281
282
283 <!-- ##### FUNCTION gdk_threads_leave ##### -->
284 <para>
285 Leaves a critical region begun with gdk_threads_enter(). 
286 </para>
287
288
289
290 <!-- ##### VARIABLE gdk_threads_mutex ##### -->
291 <para>
292 The #GMutex used to implement the critical region for
293 gdk_threads_enter()/gdk_threads_leave(). This variable should not be
294 used directly &mdash; consider it private.
295 </para>
296
297
298 <!-- ##### FUNCTION gdk_threads_set_lock_functions ##### -->
299 <para>
300
301 </para>
302
303 @enter_fn: 
304 @leave_fn: 
305
306