~ubuntu-branches/ubuntu/precise/gtk+2.0/precise-updates

« back to all changes in this revision

Viewing changes to docs/reference/gdk/tmpl/threads.sgml

  • Committer: Package Import Robot
  • Author(s): Ken VanDine
  • Date: 2011-12-01 11:40:06 UTC
  • mfrom: (1.14.11)
  • Revision ID: package-import@ubuntu.com-20111201114006-nrmf6qu3pg512veo
Tags: 2.24.8-0ubuntu1
* New upstream release 
  - gtkfilechooser should be more robust to malformed URIs
    in .gtk-bookmarks (LP: #189494)
* debian/patches/010_make_bg_changes_queue_repaint.patch
  - dropped it introduces performance regressions in some gtk2 
    apps (LP: #889019)
* 101_filechooser.patch, 000git_file_chooser.patch: dropped, upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
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