forked from AuroraMiddleware/gtk
docs: Move documentation to inline comments: gdkthreads
This commit is contained in:
parent
4400f997a8
commit
b63800bd33
1
docs/reference/gdk/tmpl/.gitignore
vendored
1
docs/reference/gdk/tmpl/.gitignore
vendored
@ -15,5 +15,6 @@ properties.sgml
|
||||
pixbufs.sgml
|
||||
regions.sgml
|
||||
selections.sgml
|
||||
threads.sgml
|
||||
visuals.sgml
|
||||
windows.sgml
|
||||
|
@ -1,381 +0,0 @@
|
||||
<!-- ##### SECTION Title ##### -->
|
||||
Threads
|
||||
|
||||
<!-- ##### SECTION Short_Description ##### -->
|
||||
Functions for using GDK in multi-threaded programs
|
||||
|
||||
<!-- ##### SECTION Long_Description ##### -->
|
||||
<para>
|
||||
For thread safety, GDK relies on the thread primitives in GLib,
|
||||
and on the thread-safe GLib main loop.
|
||||
</para>
|
||||
<para>
|
||||
GLib is completely thread safe (all global data is automatically
|
||||
locked), but individual data structure instances are not automatically
|
||||
locked for performance reasons. So e.g. you must coordinate
|
||||
accesses to the same #GHashTable from multiple threads.
|
||||
</para>
|
||||
<para>
|
||||
GTK+ is "thread aware" but not thread safe — it provides a
|
||||
global lock controlled by gdk_threads_enter()/gdk_threads_leave()
|
||||
which protects all use of GTK+. That is, only one thread can use GTK+
|
||||
at any given time.
|
||||
</para>
|
||||
<para>
|
||||
Unfortunately the above holds with the X11 backend only. With the
|
||||
Win32 backend, GDK calls should not be attempted from multiple threads
|
||||
at all.
|
||||
</para>
|
||||
<para>
|
||||
You must call g_thread_init() and gdk_threads_init() before executing
|
||||
any other GTK+ or GDK functions in a threaded GTK+ program.
|
||||
</para>
|
||||
<para>
|
||||
Idles, timeouts, and input functions from GLib, such as g_idle_add(), are
|
||||
executed outside of the main GTK+ lock.
|
||||
So, if you need to call GTK+ inside of such a callback, you must surround
|
||||
the callback with a gdk_threads_enter()/gdk_threads_leave() pair or use
|
||||
gdk_threads_add_idle_full() which does this for you.
|
||||
However, event dispatching from the mainloop is still executed within
|
||||
the main GTK+ lock, so callback functions connected to event signals
|
||||
like GtkWidget::button-press-event, do not need thread protection.
|
||||
</para>
|
||||
<para>
|
||||
In particular, this means, if you are writing widgets that might
|
||||
be used in threaded programs, you <emphasis>must</emphasis> surround
|
||||
timeouts and idle functions in this matter.
|
||||
</para>
|
||||
<para>
|
||||
As always, you must also surround any calls to GTK+ not made within
|
||||
a signal handler with a gdk_threads_enter()/gdk_threads_leave() pair.
|
||||
</para>
|
||||
|
||||
<para>
|
||||
Before calling gdk_threads_leave() from a thread other
|
||||
than your main thread, you probably want to call gdk_flush()
|
||||
to send all pending commands to the windowing system.
|
||||
(The reason you don't need to do this from the main thread
|
||||
is that GDK always automatically flushes pending commands
|
||||
when it runs out of incoming events to process and has
|
||||
to sleep while waiting for more events.)
|
||||
</para>
|
||||
|
||||
<para>A minimal main program for a threaded GTK+ application
|
||||
looks like:</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting role="C">
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GtkWidget *window;
|
||||
|
||||
g_thread_init (NULL);
|
||||
gdk_threads_init (<!-- -->);
|
||||
gdk_threads_enter (<!-- -->);
|
||||
|
||||
gtk_init (&argc, &argv);
|
||||
|
||||
window = create_window (<!-- -->);
|
||||
gtk_widget_show (window);
|
||||
|
||||
gtk_main (<!-- -->);
|
||||
gdk_threads_leave (<!-- -->);
|
||||
|
||||
return 0;
|
||||
}
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
|
||||
<para>
|
||||
Callbacks require a bit of attention. Callbacks from GTK+ signals
|
||||
are made within the GTK+ lock. However callbacks from GLib (timeouts,
|
||||
IO callbacks, and idle functions) are made outside of the GTK+
|
||||
lock. So, within a signal handler you do not need to call
|
||||
gdk_threads_enter(), but within the other types of callbacks, you
|
||||
do.
|
||||
</para>
|
||||
|
||||
<para>Erik Mouw contributed the following code example to
|
||||
illustrate how to use threads within GTK+ programs.
|
||||
</para>
|
||||
|
||||
<informalexample>
|
||||
<programlisting role="C">
|
||||
/*-------------------------------------------------------------------------
|
||||
* Filename: gtk-thread.c
|
||||
* Version: 0.99.1
|
||||
* Copyright: Copyright (C) 1999, Erik Mouw
|
||||
* Author: Erik Mouw <J.A.K.Mouw@its.tudelft.nl>
|
||||
* Description: GTK threads example.
|
||||
* Created at: Sun Oct 17 21:27:09 1999
|
||||
* Modified by: Erik Mouw <J.A.K.Mouw@its.tudelft.nl>
|
||||
* Modified at: Sun Oct 24 17:21:41 1999
|
||||
*-----------------------------------------------------------------------*/
|
||||
/*
|
||||
* Compile with:
|
||||
*
|
||||
* cc -o gtk-thread gtk-thread.c `gtk-config --cflags --libs gthread`
|
||||
*
|
||||
* Thanks to Sebastian Wilhelmi and Owen Taylor for pointing out some
|
||||
* bugs.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <time.h>
|
||||
#include <gtk/gtk.h>
|
||||
#include <glib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define YES_IT_IS (1)
|
||||
#define NO_IT_IS_NOT (0)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
GtkWidget *label;
|
||||
int what;
|
||||
} yes_or_no_args;
|
||||
|
||||
G_LOCK_DEFINE_STATIC (yes_or_no);
|
||||
static volatile int yes_or_no = YES_IT_IS;
|
||||
|
||||
void destroy (GtkWidget *widget, gpointer data)
|
||||
{
|
||||
gtk_main_quit (<!-- -->);
|
||||
}
|
||||
|
||||
void *argument_thread (void *args)
|
||||
{
|
||||
yes_or_no_args *data = (yes_or_no_args *)args;
|
||||
gboolean say_something;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
/* sleep a while */
|
||||
sleep(rand(<!-- -->) / (RAND_MAX / 3) + 1);
|
||||
|
||||
/* lock the yes_or_no_variable */
|
||||
G_LOCK(yes_or_no);
|
||||
|
||||
/* do we have to say something? */
|
||||
say_something = (yes_or_no != data->what);
|
||||
|
||||
if(say_something)
|
||||
{
|
||||
/* set the variable */
|
||||
yes_or_no = data->what;
|
||||
}
|
||||
|
||||
/* Unlock the yes_or_no variable */
|
||||
G_UNLOCK (yes_or_no);
|
||||
|
||||
if (say_something)
|
||||
{
|
||||
/* get GTK thread lock */
|
||||
gdk_threads_enter (<!-- -->);
|
||||
|
||||
/* set label text */
|
||||
if(data->what == YES_IT_IS)
|
||||
gtk_label_set_text (GTK_LABEL (data->label), "O yes, it is!");
|
||||
else
|
||||
gtk_label_set_text (GTK_LABEL (data->label), "O no, it isn't!");
|
||||
|
||||
/* release GTK thread lock */
|
||||
gdk_threads_leave (<!-- -->);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int main (int argc, char *argv[])
|
||||
{
|
||||
GtkWidget *window;
|
||||
GtkWidget *label;
|
||||
yes_or_no_args yes_args, no_args;
|
||||
pthread_t no_tid, yes_tid;
|
||||
|
||||
/* init threads */
|
||||
g_thread_init (NULL);
|
||||
gdk_threads_init (<!-- -->);
|
||||
gdk_threads_enter (<!-- -->);
|
||||
|
||||
/* init gtk */
|
||||
gtk_init(&argc, &argv);
|
||||
|
||||
/* init random number generator */
|
||||
srand ((unsigned int) time (NULL));
|
||||
|
||||
/* create a window */
|
||||
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
|
||||
g_signal_connect (window, "destroy", G_CALLBACK (destroy), NULL);
|
||||
|
||||
gtk_container_set_border_width (GTK_CONTAINER (window), 10);
|
||||
|
||||
/* create a label */
|
||||
label = gtk_label_new ("And now for something completely different ...");
|
||||
gtk_container_add (GTK_CONTAINER (window), label);
|
||||
|
||||
/* show everything */
|
||||
gtk_widget_show (label);
|
||||
gtk_widget_show (window);
|
||||
|
||||
/* create the threads */
|
||||
yes_args.label = label;
|
||||
yes_args.what = YES_IT_IS;
|
||||
pthread_create (&yes_tid, NULL, argument_thread, &yes_args);
|
||||
|
||||
no_args.label = label;
|
||||
no_args.what = NO_IT_IS_NOT;
|
||||
pthread_create (&no_tid, NULL, argument_thread, &no_args);
|
||||
|
||||
/* enter the GTK main loop */
|
||||
gtk_main (<!-- -->);
|
||||
gdk_threads_leave (<!-- -->);
|
||||
|
||||
return 0;
|
||||
}
|
||||
</programlisting>
|
||||
</informalexample>
|
||||
|
||||
<!-- ##### SECTION See_Also ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
<!-- ##### SECTION Stability_Level ##### -->
|
||||
|
||||
|
||||
<!-- ##### SECTION Image ##### -->
|
||||
|
||||
|
||||
<!-- ##### MACRO GDK_THREADS_ENTER ##### -->
|
||||
<para>
|
||||
This macro marks the beginning of a critical section in which GDK and
|
||||
GTK+ functions can be called safely and without causing race
|
||||
conditions. Only one thread at a time can be in such a critial
|
||||
section. The macro expands to a no-op if #G_THREADS_ENABLED has not
|
||||
been defined. Typically gdk_threads_enter() should be used instead of
|
||||
this macro.
|
||||
</para>
|
||||
|
||||
|
||||
|
||||
<!-- ##### MACRO GDK_THREADS_LEAVE ##### -->
|
||||
<para>
|
||||
This macro marks the end of a critical section
|
||||
begun with #GDK_THREADS_ENTER.
|
||||
</para>
|
||||
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gdk_threads_init ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@void:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gdk_threads_enter ##### -->
|
||||
<para>
|
||||
This macro marks the beginning of a critical section in which GDK and
|
||||
GTK+ functions can be called safely and without causing race
|
||||
conditions. Only one thread at a time can be in such a critial
|
||||
section.
|
||||
</para>
|
||||
|
||||
@void:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gdk_threads_leave ##### -->
|
||||
<para>
|
||||
Leaves a critical region begun with gdk_threads_enter().
|
||||
</para>
|
||||
|
||||
@void:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gdk_threads_set_lock_functions ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@enter_fn:
|
||||
@leave_fn:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gdk_threads_add_idle ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@function:
|
||||
@data:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gdk_threads_add_idle_full ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@priority:
|
||||
@function:
|
||||
@data:
|
||||
@notify:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gdk_threads_add_timeout ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@interval:
|
||||
@function:
|
||||
@data:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gdk_threads_add_timeout_full ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@priority:
|
||||
@interval:
|
||||
@function:
|
||||
@data:
|
||||
@notify:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gdk_threads_add_timeout_seconds ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@interval:
|
||||
@function:
|
||||
@data:
|
||||
@Returns:
|
||||
|
||||
|
||||
<!-- ##### FUNCTION gdk_threads_add_timeout_seconds_full ##### -->
|
||||
<para>
|
||||
|
||||
</para>
|
||||
|
||||
@priority:
|
||||
@interval:
|
||||
@function:
|
||||
@data:
|
||||
@notify:
|
||||
@Returns:
|
||||
|
||||
|
245
gdk/gdk.c
245
gdk/gdk.c
@ -399,6 +399,244 @@ gdk_init (int *argc, char ***argv)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* SECTION:threads
|
||||
* @Short_description: Functions for using GDK in multi-threaded programs
|
||||
* @Title: Threads
|
||||
*
|
||||
* For thread safety, GDK relies on the thread primitives in GLib,
|
||||
* and on the thread-safe GLib main loop.
|
||||
*
|
||||
* GLib is completely thread safe (all global data is automatically
|
||||
* locked), but individual data structure instances are not automatically
|
||||
* locked for performance reasons. So e.g. you must coordinate
|
||||
* accesses to the same #GHashTable from multiple threads.
|
||||
*
|
||||
* GTK+ is "thread aware" but not thread safe — it provides a
|
||||
* global lock controlled by gdk_threads_enter()/gdk_threads_leave()
|
||||
* which protects all use of GTK+. That is, only one thread can use GTK+
|
||||
* at any given time.
|
||||
*
|
||||
* Unfortunately the above holds with the X11 backend only. With the
|
||||
* Win32 backend, GDK calls should not be attempted from multiple threads
|
||||
* at all.
|
||||
*
|
||||
* You must call g_thread_init() and gdk_threads_init() before executing
|
||||
* any other GTK+ or GDK functions in a threaded GTK+ program.
|
||||
*
|
||||
* Idles, timeouts, and input functions from GLib, such as g_idle_add(), are
|
||||
* executed outside of the main GTK+ lock.
|
||||
* So, if you need to call GTK+ inside of such a callback, you must surround
|
||||
* the callback with a gdk_threads_enter()/gdk_threads_leave() pair or use
|
||||
* gdk_threads_add_idle_full() which does this for you.
|
||||
* However, event dispatching from the mainloop is still executed within
|
||||
* the main GTK+ lock, so callback functions connected to event signals
|
||||
* like #GtkWidget::button-press-event, do not need thread protection.
|
||||
*
|
||||
* In particular, this means, if you are writing widgets that might
|
||||
* be used in threaded programs, you <emphasis>must</emphasis> surround
|
||||
* timeouts and idle functions in this matter.
|
||||
*
|
||||
* As always, you must also surround any calls to GTK+ not made within
|
||||
* a signal handler with a gdk_threads_enter()/gdk_threads_leave() pair.
|
||||
*
|
||||
* Before calling gdk_threads_leave() from a thread other
|
||||
* than your main thread, you probably want to call gdk_flush()
|
||||
* to send all pending commands to the windowing system.
|
||||
* (The reason you don't need to do this from the main thread
|
||||
* is that GDK always automatically flushes pending commands
|
||||
* when it runs out of incoming events to process and has
|
||||
* to sleep while waiting for more events.)
|
||||
*
|
||||
* A minimal main program for a threaded GTK+ application
|
||||
* looks like:
|
||||
* <informalexample>
|
||||
* <programlisting role="C">
|
||||
* int
|
||||
* main (int argc, char *argv[])
|
||||
* {
|
||||
* GtkWidget *window;
|
||||
*
|
||||
* g_thread_init (NULL);
|
||||
* gdk_threads_init (<!-- -->);
|
||||
* gdk_threads_enter (<!-- -->);
|
||||
*
|
||||
* gtk_init (&argc, &argv);
|
||||
*
|
||||
* window = create_window (<!-- -->);
|
||||
* gtk_widget_show (window);
|
||||
*
|
||||
* gtk_main (<!-- -->);
|
||||
* gdk_threads_leave (<!-- -->);
|
||||
*
|
||||
* return 0;
|
||||
* }
|
||||
* </programlisting>
|
||||
* </informalexample>
|
||||
*
|
||||
* Callbacks require a bit of attention. Callbacks from GTK+ signals
|
||||
* are made within the GTK+ lock. However callbacks from GLib (timeouts,
|
||||
* IO callbacks, and idle functions) are made outside of the GTK+
|
||||
* lock. So, within a signal handler you do not need to call
|
||||
* gdk_threads_enter(), but within the other types of callbacks, you
|
||||
* do.
|
||||
*
|
||||
* Erik Mouw contributed the following code example to
|
||||
* illustrate how to use threads within GTK+ programs.
|
||||
* <informalexample>
|
||||
* <programlisting role="C">
|
||||
* /<!---->*-------------------------------------------------------------------------
|
||||
* * Filename: gtk-thread.c
|
||||
* * Version: 0.99.1
|
||||
* * Copyright: Copyright (C) 1999, Erik Mouw
|
||||
* * Author: Erik Mouw <J.A.K.Mouw@its.tudelft.nl>
|
||||
* * Description: GTK threads example.
|
||||
* * Created at: Sun Oct 17 21:27:09 1999
|
||||
* * Modified by: Erik Mouw <J.A.K.Mouw@its.tudelft.nl>
|
||||
* * Modified at: Sun Oct 24 17:21:41 1999
|
||||
* *-----------------------------------------------------------------------*<!---->/
|
||||
* /<!---->*
|
||||
* * Compile with:
|
||||
* *
|
||||
* * cc -o gtk-thread gtk-thread.c `gtk-config --cflags --libs gthread`
|
||||
* *
|
||||
* * Thanks to Sebastian Wilhelmi and Owen Taylor for pointing out some
|
||||
* * bugs.
|
||||
* *
|
||||
* *<!---->/
|
||||
*
|
||||
* #include <stdio.h>
|
||||
* #include <stdlib.h>
|
||||
* #include <unistd.h>
|
||||
* #include <time.h>
|
||||
* #include <gtk/gtk.h>
|
||||
* #include <glib.h>
|
||||
* #include <pthread.h>
|
||||
*
|
||||
* #define YES_IT_IS (1)
|
||||
* #define NO_IT_IS_NOT (0)
|
||||
*
|
||||
* typedef struct
|
||||
* {
|
||||
* GtkWidget *label;
|
||||
* int what;
|
||||
* } yes_or_no_args;
|
||||
*
|
||||
* G_LOCK_DEFINE_STATIC (yes_or_no);
|
||||
* static volatile int yes_or_no = YES_IT_IS;
|
||||
*
|
||||
* void destroy (GtkWidget *widget, gpointer data)
|
||||
* {
|
||||
* gtk_main_quit (<!-- -->);
|
||||
* }
|
||||
*
|
||||
* void *argument_thread (void *args)
|
||||
* {
|
||||
* yes_or_no_args *data = (yes_or_no_args *)args;
|
||||
* gboolean say_something;
|
||||
*
|
||||
* for (;;)
|
||||
* {
|
||||
* /<!---->* sleep a while *<!---->/
|
||||
* sleep(rand(<!-- -->) / (RAND_MAX / 3) + 1);
|
||||
*
|
||||
* /<!---->* lock the yes_or_no_variable *<!---->/
|
||||
* G_LOCK(yes_or_no);
|
||||
*
|
||||
* /<!---->* do we have to say something? *<!---->/
|
||||
* say_something = (yes_or_no != data->what);
|
||||
*
|
||||
* if(say_something)
|
||||
* {
|
||||
* /<!---->* set the variable *<!---->/
|
||||
* yes_or_no = data->what;
|
||||
* }
|
||||
*
|
||||
* /<!---->* Unlock the yes_or_no variable *<!---->/
|
||||
* G_UNLOCK (yes_or_no);
|
||||
*
|
||||
* if (say_something)
|
||||
* {
|
||||
* /<!---->* get GTK thread lock *<!---->/
|
||||
* gdk_threads_enter (<!-- -->);
|
||||
*
|
||||
* /<!---->* set label text *<!---->/
|
||||
* if(data->what == YES_IT_IS)
|
||||
* gtk_label_set_text (GTK_LABEL (data->label), "O yes, it is!");
|
||||
* else
|
||||
* gtk_label_set_text (GTK_LABEL (data->label), "O no, it isn't!");
|
||||
*
|
||||
* /<!---->* release GTK thread lock *<!---->/
|
||||
* gdk_threads_leave (<!-- -->);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* return NULL;
|
||||
* }
|
||||
*
|
||||
* int main (int argc, char *argv[])
|
||||
* {
|
||||
* GtkWidget *window;
|
||||
* GtkWidget *label;
|
||||
* yes_or_no_args yes_args, no_args;
|
||||
* pthread_t no_tid, yes_tid;
|
||||
*
|
||||
* /<!---->* init threads *<!---->/
|
||||
* g_thread_init (NULL);
|
||||
* gdk_threads_init (<!-- -->);
|
||||
* gdk_threads_enter (<!-- -->);
|
||||
*
|
||||
* /<!---->* init gtk *<!---->/
|
||||
* gtk_init(&argc, &argv);
|
||||
*
|
||||
* /<!---->* init random number generator *<!---->/
|
||||
* srand ((unsigned int) time (NULL));
|
||||
*
|
||||
* /<!---->* create a window *<!---->/
|
||||
* window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
*
|
||||
* g_signal_connect (window, "destroy", G_CALLBACK (destroy), NULL);
|
||||
*
|
||||
* gtk_container_set_border_width (GTK_CONTAINER (window), 10);
|
||||
*
|
||||
* /<!---->* create a label *<!---->/
|
||||
* label = gtk_label_new ("And now for something completely different ...");
|
||||
* gtk_container_add (GTK_CONTAINER (window), label);
|
||||
*
|
||||
* /<!---->* show everything *<!---->/
|
||||
* gtk_widget_show (label);
|
||||
* gtk_widget_show (window);
|
||||
*
|
||||
* /<!---->* create the threads *<!---->/
|
||||
* yes_args.label = label;
|
||||
* yes_args.what = YES_IT_IS;
|
||||
* pthread_create (&yes_tid, NULL, argument_thread, &yes_args);
|
||||
*
|
||||
* no_args.label = label;
|
||||
* no_args.what = NO_IT_IS_NOT;
|
||||
* pthread_create (&no_tid, NULL, argument_thread, &no_args);
|
||||
*
|
||||
* /<!---->* enter the GTK main loop *<!---->/
|
||||
* gtk_main (<!-- -->);
|
||||
* gdk_threads_leave (<!-- -->);
|
||||
*
|
||||
* return 0;
|
||||
* }
|
||||
* </programlisting>
|
||||
* </informalexample>
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* gdk_threads_enter:
|
||||
*
|
||||
* This macro marks the beginning of a critical section in which GDK and
|
||||
* GTK+ functions can be called safely and without causing race
|
||||
* conditions. Only one thread at a time can be in such a critial
|
||||
* section.
|
||||
*/
|
||||
void
|
||||
gdk_threads_enter (void)
|
||||
{
|
||||
@ -406,6 +644,11 @@ gdk_threads_enter (void)
|
||||
(*gdk_threads_lock) ();
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_threads_leave:
|
||||
*
|
||||
* Leaves a critical region begun with gdk_threads_enter().
|
||||
*/
|
||||
void
|
||||
gdk_threads_leave (void)
|
||||
{
|
||||
@ -429,7 +672,7 @@ gdk_threads_impl_unlock (void)
|
||||
|
||||
/**
|
||||
* gdk_threads_init:
|
||||
*
|
||||
*
|
||||
* Initializes GDK so that it can be used from multiple threads
|
||||
* in conjunction with gdk_threads_enter() and gdk_threads_leave().
|
||||
* g_thread_init() must be called previous to this function.
|
||||
|
@ -64,7 +64,24 @@ guint gdk_threads_add_timeout_seconds (guint interval,
|
||||
GSourceFunc function,
|
||||
gpointer data);
|
||||
|
||||
/**
|
||||
* GDK_THREADS_ENTER:
|
||||
*
|
||||
* This macro marks the beginning of a critical section in which GDK and
|
||||
* GTK+ functions can be called safely and without causing race
|
||||
* conditions. Only one thread at a time can be in such a critial
|
||||
* section. The macro expands to a no-op if #G_THREADS_ENABLED has not
|
||||
* been defined. Typically gdk_threads_enter() should be used instead of
|
||||
* this macro.
|
||||
*/
|
||||
#define GDK_THREADS_ENTER() gdk_threads_enter()
|
||||
|
||||
/**
|
||||
* GDK_THREADS_LEAVE:
|
||||
*
|
||||
* This macro marks the end of a critical section
|
||||
* begun with #GDK_THREADS_ENTER.
|
||||
*/
|
||||
#define GDK_THREADS_LEAVE() gdk_threads_leave()
|
||||
|
||||
G_END_DECLS
|
||||
|
Loading…
Reference in New Issue
Block a user