1
<refentry id="gdk-Threads">
3
<refentrytitle role="top_of_page">Threads</refentrytitle>
4
<manvolnum>3</manvolnum>
5
<refmiscinfo>GDK Library</refmiscinfo>
9
<refname>Threads</refname>
10
<refpurpose>Functions for using GDK in multi-threaded programs</refpurpose>
11
<!--[<xref linkend="desc" endterm="desc.title"/>]-->
14
<refsynopsisdiv role="synopsis">
15
<title role="synopsis.title">Synopsis</title>
19
#include <gdk/gdk.h>
22
#define <link linkend="GDK-THREADS-ENTER:CAPS">GDK_THREADS_ENTER</link> ()
23
#define <link linkend="GDK-THREADS-LEAVE:CAPS">GDK_THREADS_LEAVE</link> ()
24
<link linkend="void">void</link> <link linkend="gdk-threads-init">gdk_threads_init</link> (void);
25
<link linkend="void">void</link> <link linkend="gdk-threads-enter">gdk_threads_enter</link> (void);
26
<link linkend="void">void</link> <link linkend="gdk-threads-leave">gdk_threads_leave</link> (void);
27
extern GMutex *<link linkend="gdk-threads-mutex">gdk_threads_mutex</link>;
28
<link linkend="void">void</link> <link linkend="gdk-threads-set-lock-functions">gdk_threads_set_lock_functions</link> (<link linkend="GCallback">GCallback</link> enter_fn,
29
<link linkend="GCallback">GCallback</link> leave_fn);
42
<refsect1 role="desc">
43
<title role="desc.title">Description</title>
45
For thread safety, GDK relies on the thread primitives in GLib,
46
and on the thread-safe GLib main loop.
49
GLib is completely thread safe (all global data is automatically
50
locked), but individual data structure instances are not automatically
51
locked for performance reasons. So e.g. you must coordinate
52
accesses to the same <link linkend="GHashTable"><type>GHashTable</type></link> from multiple threads.
55
GTK+ is "thread aware" but not thread safe — it provides a
56
global lock controlled by <link linkend="gdk-threads-enter"><function>gdk_threads_enter()</function></link>/<link linkend="gdk-threads-leave"><function>gdk_threads_leave()</function></link>
57
which protects all use of GTK+. That is, only one thread can use GTK+
61
Unfortunately the above holds with the X11 backend only. With the
62
Win32 backend, GDK calls should not be attempted from multiple threads
66
You must call <link linkend="g-thread-init"><function>g_thread_init()</function></link> and <link linkend="gdk-threads-init"><function>gdk_threads_init()</function></link> before executing
67
any other GTK+ or GDK functions in a threaded GTK+ program.
70
Idles, timeouts, and input functions are executed outside
71
of the main GTK+ lock. So, if you need to call GTK+
72
inside of such a callback, you must surround the callback
73
with a <link linkend="gdk-threads-enter"><function>gdk_threads_enter()</function></link>/<link linkend="gdk-threads-leave"><function>gdk_threads_leave()</function></link> pair.
74
(However, signals are still executed within the main
78
In particular, this means, if you are writing widgets that might
79
be used in threaded programs, you <emphasis>must</emphasis> surround
80
timeouts and idle functions in this matter.
83
As always, you must also surround any calls to GTK+ not made within
84
a signal handler with a <link linkend="gdk-threads-enter"><function>gdk_threads_enter()</function></link>/<link linkend="gdk-threads-leave"><function>gdk_threads_leave()</function></link> pair.
88
Before calling <link linkend="gdk-threads-leave"><function>gdk_threads_leave()</function></link> from a thread other
89
than your main thread, you probably want to call <link linkend="gdk-flush"><function>gdk_flush()</function></link>
90
to send all pending commands to the windowing system.
91
(The reason you don't need to do this from the main thread
92
is that GDK always automatically flushes pending commands
93
when it runs out of incoming events to process and has
94
to sleep while waiting for more events.)
97
<para>A minimal main program for a threaded GTK+ application
101
<programlisting role="C">
103
main (int argc, char *argv[])
107
g_thread_init (NULL);
108
gdk_threads_init (<!-- -->);
109
gdk_threads_enter (<!-- -->);
111
gtk_init (&argc, &argv);
113
window = create_window (<!-- -->);
114
gtk_widget_show (window);
117
gdk_threads_leave (<!-- -->);
125
Callbacks require a bit of attention. Callbacks from GTK+ signals
126
are made within the GTK+ lock. However callbacks from GLib (timeouts,
127
IO callbacks, and idle functions) are made outside of the GTK+
128
lock. So, within a signal handler you do not need to call
129
<link linkend="gdk-threads-enter"><function>gdk_threads_enter()</function></link>, but within the other types of callbacks, you
133
<para>Erik Mouw contributed the following code example to
134
illustrate how to use threads within GTK+ programs.
138
<programlisting role="C">
139
/*-------------------------------------------------------------------------
140
* Filename: gtk-thread.c
142
* Copyright: Copyright (C) 1999, Erik Mouw
143
* Author: Erik Mouw <J.A.K.Mouw@its.tudelft.nl>
144
* Description: GTK threads example.
145
* Created at: Sun Oct 17 21:27:09 1999
146
* Modified by: Erik Mouw <J.A.K.Mouw@its.tudelft.nl>
147
* Modified at: Sun Oct 24 17:21:41 1999
148
*-----------------------------------------------------------------------*/
152
* cc -o gtk-thread gtk-thread.c `gtk-config --cflags --libs gthread`
154
* Thanks to Sebastian Wilhelmi and Owen Taylor for pointing out some
159
#include <stdio.h>
160
#include <stdlib.h>
161
#include <unistd.h>
162
#include <time.h>
163
#include <gtk/gtk.h>
164
#include <glib.h>
165
#include <pthread.h>
167
#define YES_IT_IS (1)
168
#define NO_IT_IS_NOT (0)
176
G_LOCK_DEFINE_STATIC (yes_or_no);
177
static volatile int yes_or_no = YES_IT_IS;
179
void destroy (GtkWidget *widget, gpointer data)
181
gtk_main_quit (<!-- -->);
184
void *argument_thread (void *args)
186
yes_or_no_args *data = (yes_or_no_args *)args;
187
gboolean say_something;
192
sleep(rand(<!-- -->) / (RAND_MAX / 3) + 1);
194
/* lock the yes_or_no_variable */
197
/* do we have to say something? */
198
say_something = (yes_or_no != data->what);
202
/* set the variable */
203
yes_or_no = data->what;
206
/* Unlock the yes_or_no variable */
207
G_UNLOCK (yes_or_no);
211
/* get GTK thread lock */
212
gdk_threads_enter (<!-- -->);
215
if(data->what == YES_IT_IS)
216
gtk_label_set_text (GTK_LABEL (data->label), "O yes, it is!");
218
gtk_label_set_text (GTK_LABEL (data->label), "O no, it isn't!");
220
/* release GTK thread lock */
221
gdk_threads_leave (<!-- -->);
228
int main (int argc, char *argv[])
232
yes_or_no_args yes_args, no_args;
233
pthread_t no_tid, yes_tid;
236
g_thread_init (NULL);
237
gdk_threads_init (<!-- -->);
238
gdk_threads_enter (<!-- -->);
241
gtk_init(&argc, &argv);
243
/* init random number generator */
244
srand ((unsigned int) time (NULL));
246
/* create a window */
247
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
249
gtk_signal_connect (GTK_OBJECT (window), "destroy",
250
GTK_SIGNAL_FUNC (destroy), NULL);
252
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
255
label = gtk_label_new ("And now for something completely different ...");
256
gtk_container_add (GTK_CONTAINER (window), label);
258
/* show everything */
259
gtk_widget_show (label);
260
gtk_widget_show (window);
262
/* create the threads */
263
yes_args.label = label;
264
yes_args.what = YES_IT_IS;
265
pthread_create (&yes_tid, NULL, argument_thread, &yes_args);
267
no_args.label = label;
268
no_args.what = NO_IT_IS_NOT;
269
pthread_create (&no_tid, NULL, argument_thread, &no_args);
271
/* enter the GTK main loop */
273
gdk_threads_leave (<!-- -->);
281
<refsect1 role="details">
282
<title role="details.title">Details</title>
284
<title><anchor id="GDK-THREADS-ENTER:CAPS" role="macro"/>GDK_THREADS_ENTER()</title>
285
<indexterm><primary>GDK_THREADS_ENTER</primary></indexterm><programlisting>#define GDK_THREADS_ENTER()</programlisting>
287
This macro marks the beginning of a critical section in which GDK and GTK+
288
functions can be called. Only one thread at a time can be in such a
289
critial section. The macro expands to a no-op if <link linkend="G-THREADS-ENABLED:CAPS"><type>G_THREADS_ENABLED</type></link>
290
has not been defined. Typically <link linkend="gdk-threads-enter"><function>gdk_threads_enter()</function></link> should be used
291
instead of this macro.
294
<title><anchor id="GDK-THREADS-LEAVE:CAPS" role="macro"/>GDK_THREADS_LEAVE()</title>
295
<indexterm><primary>GDK_THREADS_LEAVE</primary></indexterm><programlisting>#define GDK_THREADS_LEAVE()</programlisting>
297
This macro marks the end of a critical section
298
begun with <link linkend="GDK-THREADS-ENTER:CAPS"><type>GDK_THREADS_ENTER</type></link>.
301
<title><anchor id="gdk-threads-init" role="function"/>gdk_threads_init ()</title>
302
<indexterm><primary>gdk_threads_init</primary></indexterm><programlisting><link linkend="void">void</link> gdk_threads_init (void);</programlisting>
304
Initializes GDK so that it can be used from multiple threads
305
in conjunction with <link linkend="gdk-threads-enter"><function>gdk_threads_enter()</function></link> and <link linkend="gdk-threads-leave"><function>gdk_threads_leave()</function></link>.
306
<link linkend="g-thread-init"><function>g_thread_init()</function></link> must be called previous to this function.
309
This call must be made before any use of the main loop from
310
GTK+; to be safe, call it before <link linkend="gtk-init"><function>gtk_init()</function></link>.</para>
315
<title><anchor id="gdk-threads-enter" role="function"/>gdk_threads_enter ()</title>
316
<indexterm><primary>gdk_threads_enter</primary></indexterm><programlisting><link linkend="void">void</link> gdk_threads_enter (void);</programlisting>
318
This macro marks the beginning of a critical section
319
in which GDK and GTK+ functions can be called.
320
Only one thread at a time can be in such a critial
324
<title><anchor id="gdk-threads-leave" role="function"/>gdk_threads_leave ()</title>
325
<indexterm><primary>gdk_threads_leave</primary></indexterm><programlisting><link linkend="void">void</link> gdk_threads_leave (void);</programlisting>
327
Leaves a critical region begun with <link linkend="gdk-threads-enter"><function>gdk_threads_enter()</function></link>.
330
<title><anchor id="gdk-threads-mutex" role="variable" condition="deprecated:"/>gdk_threads_mutex</title>
331
<indexterm role="deprecated"><primary>gdk_threads_mutex</primary></indexterm><programlisting>extern GMutex *gdk_threads_mutex; /* private */
333
<warning><para><literal>gdk_threads_mutex</literal> is deprecated and should not be used in newly-written code.</para></warning>
335
The <link linkend="GMutex"><type>GMutex</type></link> used to implement the critical region for
336
<link linkend="gdk-threads-enter"><function>gdk_threads_enter()</function></link>/<link linkend="gdk-threads-leave"><function>gdk_threads_leave()</function></link>.
339
<title><anchor id="gdk-threads-set-lock-functions" role="function" condition="since:2.4"/>gdk_threads_set_lock_functions ()</title>
340
<indexterm role="2.4"><primary>gdk_threads_set_lock_functions</primary></indexterm><programlisting><link linkend="void">void</link> gdk_threads_set_lock_functions (<link linkend="GCallback">GCallback</link> enter_fn,
341
<link linkend="GCallback">GCallback</link> leave_fn);</programlisting>
343
Allows the application to replace the standard method that
344
GDK uses to protect its data structures. Normally, GDK
345
creates a single <link linkend="GMutex"><type>GMutex</type></link> that is locked by <link linkend="gdk-threads-enter"><function>gdk_threads_enter()</function></link>,
346
and released by <link linkend="gdk-threads-leave"><function>gdk_threads_leave()</function></link>; using this function an
347
application provides, instead, a function <parameter>enter_fn</parameter> that is
348
called by <link linkend="gdk-threads-enter"><function>gdk_threads_enter()</function></link> and a function <parameter>leave_fn</parameter> that is
349
called by <link linkend="gdk-threads-leave"><function>gdk_threads_leave()</function></link>.
352
The functions must provide at least same locking functionality
353
as the default implementation, but can also do extra application
357
As an example, consider an application that has its own recursive
358
lock that when held, holds the GTK+ lock as well. When GTK+ unlocks
359
the GTK+ lock when entering a recursive main loop, the application
360
must temporarily release its lock as well.
363
Most threaded GTK+ apps won't need to use this method.
366
This method must be called before <link linkend="gdk-threads-init"><function>gdk_threads_init()</function></link>, and cannot
367
be called multiple times.</para>
370
</para><variablelist role="params">
371
<varlistentry><term><parameter>enter_fn</parameter> :</term>
372
<listitem><simpara> function called to guard GDK
373
</simpara></listitem></varlistentry>
374
<varlistentry><term><parameter>leave_fn</parameter> :</term>
375
<listitem><simpara> function called to release the guard
376
</simpara></listitem></varlistentry>
377
</variablelist><para role="since">Since 2.4