1999-08-16 17:58:30 +00:00
|
|
|
<!-- ##### SECTION Title ##### -->
|
2000-09-07 16:36:56 +00:00
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
Threads
|
|
|
|
|
|
|
|
<!-- ##### SECTION Short_Description ##### -->
|
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
thread abstraction; including mutexes, conditions and thread private data.
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
<!-- ##### SECTION Long_Description ##### -->
|
2000-09-07 16:36:56 +00:00
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-07 16:36:56 +00:00
|
|
|
Threads act almost like processes, but unlike processes all threads of
|
|
|
|
one process share the same memory. This is good, as it provides easy
|
|
|
|
communication between the involved threads via this shared memory, and
|
|
|
|
it is bad, because strange things (so called Heisenbugs) might happen,
|
|
|
|
when the program is not carefully designed. Especially bad is, that due
|
|
|
|
to the concurrent nature of threads no assumptions on the order of
|
|
|
|
execution of different threads can be done unless explictly forced by
|
|
|
|
the programmer through synchronization primitives.
|
|
|
|
</para>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
The aim of the thread related functions in GLib is to provide a
|
|
|
|
portable means for writing multithread safe software. There are
|
|
|
|
primitives for mutexes to protect the access to portions of memory
|
|
|
|
(#GMutex, #GStaticMutex, #G_LOCK_DEFINE and friends), there are
|
|
|
|
primitives for condition variables to allow synchronization of threads
|
|
|
|
(#GCond) and finally there are primitives for thread-private data,
|
|
|
|
that every thread has a private instance of (#GPrivate,
|
|
|
|
#GStaticPrivate).
|
|
|
|
</para>
|
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
<!-- ##### SECTION See_Also ##### -->
|
|
|
|
<para>
|
|
|
|
|
|
|
|
</para>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### MACRO G_THREADS_ENABLED ##### -->
|
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
This macro is defined, if GLib was compiled with thread support. This
|
|
|
|
does not necessarily mean, that there is a thread implementation
|
|
|
|
available, but the infrastructure is in place and once you provide a
|
|
|
|
thread implementation to g_thread_init(), GLib will be multithread
|
2001-01-30 14:16:56 +00:00
|
|
|
safe. It isn't and cannot be, if #G_THREADS_ENABLED is not defined.
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- ##### MACRO G_THREADS_IMPL_POSIX ##### -->
|
2000-09-06 00:04:49 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
This macro is defined, if POSIX style threads are used.
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- ##### MACRO G_THREADS_IMPL_SOLARIS ##### -->
|
2000-09-06 00:04:49 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
This macro is defined, if the SOLARIS thread system is used.
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- ##### MACRO G_THREADS_IMPL_NONE ##### -->
|
2000-09-06 00:04:49 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
This macro is defined, if no thread implementation is used. You can
|
|
|
|
however provide one to g_thread_init() to make GLib multithread safe.
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
|
|
|
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### MACRO G_THREAD_ERROR ##### -->
|
|
|
|
<para>
|
|
|
|
|
|
|
|
</para>
|
|
|
|
|
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### ENUM GThreadError ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-06 00:04:49 +00:00
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
@G_THREAD_ERROR_AGAIN:
|
|
|
|
|
|
|
|
<!-- ##### STRUCT GThreadFunctions ##### -->
|
2000-09-07 16:36:56 +00:00
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-07 16:36:56 +00:00
|
|
|
This function table is used by g_thread_init() to initialize the
|
|
|
|
thread system. The functions in that table are directly used by their
|
|
|
|
g_* prepended counterparts, that are described here, e.g. if you call
|
|
|
|
g_mutex_new() then mutex_new() from the table provided to
|
|
|
|
g_thread_init() will be called.
|
|
|
|
</para>
|
2000-09-06 00:04:49 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<note>
|
|
|
|
<para>
|
|
|
|
This struct should only be used, if you know, what you are doing.
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
2000-09-07 16:36:56 +00:00
|
|
|
</note>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
@mutex_new:
|
|
|
|
@mutex_lock:
|
|
|
|
@mutex_trylock:
|
|
|
|
@mutex_unlock:
|
|
|
|
@mutex_free:
|
|
|
|
@cond_new:
|
|
|
|
@cond_signal:
|
|
|
|
@cond_broadcast:
|
|
|
|
@cond_wait:
|
|
|
|
@cond_timed_wait:
|
|
|
|
@cond_free:
|
|
|
|
@private_new:
|
|
|
|
@private_get:
|
|
|
|
@private_set:
|
2000-09-06 00:04:49 +00:00
|
|
|
@thread_create:
|
|
|
|
@thread_yield:
|
|
|
|
@thread_join:
|
|
|
|
@thread_exit:
|
|
|
|
@thread_set_priority:
|
|
|
|
@thread_self:
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
<!-- ##### FUNCTION g_thread_init ##### -->
|
2000-09-07 16:36:56 +00:00
|
|
|
|
|
|
|
<para>
|
|
|
|
Before you use a thread related function in GLib, you should
|
|
|
|
initialize the thread system. This is done by calling
|
|
|
|
g_thread_init(). Most of the time you will only have to call
|
|
|
|
g_thread_init(NULL).
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<note>
|
|
|
|
<para>
|
|
|
|
You should only call g_thread_init() with a non-NULL parameter, if you
|
|
|
|
really know, what you are doing.
|
|
|
|
</para>
|
|
|
|
</note>
|
|
|
|
|
|
|
|
<note>
|
|
|
|
<para>
|
|
|
|
g_thread_init() must not be called directly or indirectly as a
|
|
|
|
callback from GLib.
|
|
|
|
</para>
|
|
|
|
</note>
|
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-07 16:36:56 +00:00
|
|
|
g_thread_init() might only be called once. On the second call
|
|
|
|
it will abort with an error. If you want to make sure, that the thread
|
|
|
|
system is initialized, you can do that too:
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
<informalexample>
|
|
|
|
<programlisting>
|
|
|
|
if (!g_thread_supported ()) g_thread_init (NULL);
|
|
|
|
</programlisting>
|
|
|
|
</informalexample>
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
After that line either the thread system is initialized or the program
|
|
|
|
will abort, if no thread system is available in GLib, i.e. either
|
|
|
|
#G_THREADS_ENABLED is not defined or #G_THREADS_IMPL_NONE is defined.
|
|
|
|
</para>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
If no thread system is available and @vtable is NULL or if not all
|
|
|
|
elements of @vtable are non-NULL, then g_thread_init() will abort.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<note>
|
|
|
|
<para>
|
|
|
|
To use g_thread_init() in your program, you have to link with the
|
|
|
|
libraries, that the command "glib-config --libs gthread" outputs. This
|
|
|
|
is not the case for all the other thread related functions of
|
|
|
|
GLib. Those can be used without having to link with the thread
|
|
|
|
libraries.
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
2000-09-07 16:36:56 +00:00
|
|
|
</note>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
@vtable: a function table of type #GThreadFunctions, that provides the
|
|
|
|
entry points to the thread system to be used.
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### FUNCTION g_thread_supported ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-07 16:36:56 +00:00
|
|
|
This function returns, whether the thread system is initialized or
|
|
|
|
not.
|
|
|
|
</para>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<note>
|
|
|
|
<para>
|
|
|
|
This function is actually a macro. Apart from taking the address of it
|
|
|
|
you can however use it as if it was a function.
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
2000-09-07 16:36:56 +00:00
|
|
|
</note>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
@Returns: TRUE, if the thread system is initialized.
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### USER_FUNCTION GThreadFunc ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
|
|
|
|
|
|
|
</para>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
@value:
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### ENUM GThreadPriority ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
|
|
|
|
|
|
|
</para>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
@G_THREAD_PRIORITY_LOW:
|
|
|
|
@G_THREAD_PRIORITY_NORMAL:
|
|
|
|
@G_THREAD_PRIORITY_HIGH:
|
|
|
|
@G_THREAD_PRIORITY_URGENT:
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### STRUCT GThread ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
|
|
|
|
|
|
|
</para>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
@priority:
|
|
|
|
@bound:
|
|
|
|
@joinable:
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### FUNCTION g_thread_create ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
</para>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
@thread_func:
|
|
|
|
@arg:
|
|
|
|
@stack_size:
|
|
|
|
@joinable:
|
|
|
|
@bound:
|
|
|
|
@priority:
|
|
|
|
@error:
|
|
|
|
@Returns:
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### FUNCTION g_thread_self ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
|
|
|
|
|
|
|
</para>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
@Returns:
|
|
|
|
|
|
|
|
|
|
|
|
<!-- ##### FUNCTION g_thread_join ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-06 00:04:49 +00:00
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
@thread:
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### FUNCTION g_thread_set_priority ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
|
|
|
|
|
|
|
</para>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
@thread:
|
|
|
|
@priority:
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### MACRO g_thread_yield ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
|
|
|
|
|
|
|
</para>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
|
|
|
|
|
|
|
|
<!-- ##### MACRO g_thread_exit ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
</para>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### STRUCT GMutex ##### -->
|
2000-09-07 16:36:56 +00:00
|
|
|
|
|
|
|
<para>
|
|
|
|
The #GMutex struct is an opaque data structure to represent a mutex
|
|
|
|
(mutual exclusion). It can be used to protect data against shared
|
|
|
|
access. Take for example the following function:
|
|
|
|
|
|
|
|
<example>
|
|
|
|
<title>A function which will not work in a threaded environment</title>
|
|
|
|
<programlisting>
|
|
|
|
int give_me_next_number ()
|
|
|
|
{
|
|
|
|
static int current_number = 0;
|
|
|
|
|
|
|
|
/* now do a very complicated calculation to calculate the new number,
|
|
|
|
this might for example be a random number generator */
|
|
|
|
current_number = calc_next_number (current_number);
|
|
|
|
return current_number;
|
|
|
|
}
|
|
|
|
</programlisting>
|
|
|
|
</example>
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
It is easy to see, that this won't work in a multithreaded
|
|
|
|
application. There current_number must be protected against shared
|
|
|
|
access. A first naive implementation would be:
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
<example>
|
|
|
|
<title>The wrong way to write a thread-safe function</title>
|
|
|
|
<programlisting>
|
|
|
|
int give_me_next_number ()
|
|
|
|
{
|
|
|
|
static int current_number = 0;
|
|
|
|
int ret_val;
|
|
|
|
static GMutex * mutex = NULL;
|
|
|
|
|
|
|
|
if (!mutex)
|
|
|
|
mutex = g_mutex_new ();
|
|
|
|
g_mutex_lock (mutex);
|
|
|
|
ret_val = current_number = calc_next_number (current_number);
|
|
|
|
g_mutex_unlock (mutex);
|
|
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
</programlisting>
|
|
|
|
</example>
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
This looks like it would work, but there is a race condition while
|
2001-01-30 14:16:56 +00:00
|
|
|
constructing the mutex and this code cannot work reliable. So please do
|
2000-09-07 16:36:56 +00:00
|
|
|
not use such constructs in your own programs. One working solution is:
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
<example>
|
|
|
|
<title>A correct thread-safe function</title>
|
|
|
|
<programlisting>
|
|
|
|
static GMutex *give_me_next_number_mutex = NULL;
|
|
|
|
|
|
|
|
/* this function must be called before any call to give_me_next_number ()
|
|
|
|
it must be called exactly once. */
|
|
|
|
void init_give_me_next_number ()
|
|
|
|
{
|
|
|
|
g_assert (give_me_next_number_mutex == NULL);
|
|
|
|
give_me_next_number_mutex = g_mutex_new ();
|
|
|
|
}
|
|
|
|
|
|
|
|
int give_me_next_number ()
|
|
|
|
{
|
|
|
|
static int current_number = 0;
|
|
|
|
int ret_val;
|
|
|
|
|
|
|
|
g_mutex_lock (give_me_next_number_mutex);
|
|
|
|
ret_val = current_number = calc_next_number (current_number);
|
|
|
|
g_mutex_unlock (give_me_next_number_mutex);
|
|
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
</programlisting>
|
|
|
|
</example>
|
|
|
|
</para>
|
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-07 16:36:56 +00:00
|
|
|
#GStaticMutex provides a simpler and safer way of doing this.
|
|
|
|
</para>
|
2000-09-06 00:04:49 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
A #GMutex should only be accessed via the following functions.
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<note>
|
|
|
|
<para>
|
|
|
|
All of the g_mutex_* functions are actually macros. Apart from taking
|
|
|
|
the addresses of them, you can however use them as if they were functions.
|
|
|
|
</para>
|
|
|
|
</note>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
|
|
|
|
<!-- ##### FUNCTION g_mutex_new ##### -->
|
2000-09-07 16:36:56 +00:00
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-07 16:36:56 +00:00
|
|
|
Creates a new #GMutex.
|
|
|
|
</para>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<note>
|
|
|
|
<para>
|
|
|
|
This function will abort, if g_thread_init() has not been called yet.
|
2000-09-06 00:04:49 +00:00
|
|
|
</para>
|
2000-09-07 16:36:56 +00:00
|
|
|
</note>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
@Returns: a new #GMutex.
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### FUNCTION g_mutex_lock ##### -->
|
2000-09-07 16:36:56 +00:00
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-07 16:36:56 +00:00
|
|
|
Locks the #GMutex. If the #GMutex is already locked by another thread,
|
|
|
|
the current thread will block until the #GMutex is unlocked by the
|
|
|
|
other thread.
|
|
|
|
</para>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
This function can also be used, if g_thread_init() has not yet been
|
|
|
|
called and will do nothing then.
|
2000-09-06 00:04:49 +00:00
|
|
|
</para>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<note>
|
|
|
|
<para>
|
|
|
|
#GMutex is not guaranteed to be recursive, i.e. a thread might block,
|
|
|
|
if it already has locked the #GMutex. It will deadlock then, of
|
|
|
|
course.
|
|
|
|
</para>
|
|
|
|
</note>
|
|
|
|
|
|
|
|
@mutex: a #GMutex.
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### FUNCTION g_mutex_trylock ##### -->
|
2000-09-07 16:36:56 +00:00
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-07 16:36:56 +00:00
|
|
|
Tries to lock the #GMutex. If the #GMutex is already locked by another
|
|
|
|
thread, it immediately returns FALSE. Otherwise it locks the #GMutex
|
|
|
|
and returns TRUE.
|
|
|
|
</para>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
This function can also be used, if g_thread_init() has not yet been
|
|
|
|
called and will immediately return TRUE then.
|
2000-09-06 00:04:49 +00:00
|
|
|
</para>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
@mutex: a #GMutex.
|
|
|
|
@Returns: TRUE, if the #GMutex could be locked.
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### FUNCTION g_mutex_unlock ##### -->
|
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
Unlocks the #GMutex. If another thread is blocked in a g_mutex_lock()
|
|
|
|
call, it will be woken and can lock the #GMutex itself. This function
|
|
|
|
can also be used, if g_thread_init() has not yet been called and will
|
|
|
|
do nothing then.
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
@mutex: a #GMutex.
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### FUNCTION g_mutex_free ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
Destroys the #GMutex.
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
@mutex: a #GMutex.
|
2000-09-06 00:04:49 +00:00
|
|
|
|
|
|
|
|
|
|
|
<!-- ##### STRUCT GStaticMutex ##### -->
|
2000-09-07 16:36:56 +00:00
|
|
|
|
|
|
|
<para>
|
|
|
|
A #GStaticMutex works like a #GMutex, but it has one significant
|
|
|
|
advantage. It doesn't need to be created at run-time like a #GMutex,
|
|
|
|
but can be defined at compile-time. Here is a shorter, easier and
|
|
|
|
safer version of our give_me_next_number() example:
|
|
|
|
</para>
|
|
|
|
|
2001-01-30 14:16:56 +00:00
|
|
|
<para>
|
|
|
|
Sometimes you would like to dynamically create a mutex. If you don't
|
|
|
|
want to require prior calling to g_thread_init(), because your code
|
|
|
|
should also be usable in non-threaded programs, you are not able to
|
|
|
|
use g_mutex_new() and thus #GMutex, as that requires a prior call to
|
|
|
|
g_thread_init(). In theses cases you can also use a #GStaticMutex, but
|
|
|
|
you should remember to free the #GStaticMutex with
|
|
|
|
g_static_mutex_free() when not needed anymore to free up any
|
|
|
|
allocated recourses.
|
|
|
|
</para>
|
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
<example>
|
|
|
|
<title>Using GStaticMutex to simplify thread-safe programming</title>
|
|
|
|
<programlisting>
|
|
|
|
int give_me_next_number ()
|
|
|
|
{
|
|
|
|
static int current_number = 0;
|
|
|
|
int ret_val;
|
|
|
|
static GStaticMutex mutex = G_STATIC_MUTEX_INIT;
|
|
|
|
|
|
|
|
g_static_mutex_lock (&mutex);
|
|
|
|
ret_val = current_number = calc_next_number (current_number);
|
|
|
|
g_static_mutex_unlock (&mutex);
|
|
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
</programlisting>
|
|
|
|
</example>
|
|
|
|
</para>
|
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-07 16:36:56 +00:00
|
|
|
Even though #GStaticMutex is not opaque, it should only be used with
|
|
|
|
the following functions, as it is defined differently on different
|
|
|
|
platforms.
|
|
|
|
</para>
|
2000-09-06 00:04:49 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>All of the g_static_mutex_* functions can also be used, if
|
|
|
|
g_thread_init() has not yet.
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<note>
|
|
|
|
<para>
|
|
|
|
All of the g_static_mutex_* functions are actually macros. Apart from
|
|
|
|
taking the addresses of them, you can however use them as if they were
|
|
|
|
functions.
|
|
|
|
</para>
|
|
|
|
</note>
|
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
<!-- ##### MACRO G_STATIC_MUTEX_INIT ##### -->
|
2000-09-07 16:36:56 +00:00
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-07 16:36:56 +00:00
|
|
|
Every #GStaticMutex must be initialized with this macro, before it can
|
|
|
|
be used.
|
|
|
|
</para>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
<example>
|
|
|
|
<title>Initializing a GStaticMutext</title>
|
|
|
|
<programlisting>
|
|
|
|
GStaticMutex my_mutex = G_STATIC_MUTEX_INIT;
|
|
|
|
</programlisting>
|
|
|
|
</example>
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
|
|
|
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### FUNCTION g_static_mutex_lock ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-07 16:36:56 +00:00
|
|
|
works like g_mutex_lock(), but for a #GStaticMutex.
|
2000-09-06 00:04:49 +00:00
|
|
|
</para>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
@mutex: a #GStaticMutex.
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### FUNCTION g_static_mutex_trylock ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
works like g_mutex_trylock(), but for a #GStaticMutex.
|
2000-09-06 00:04:49 +00:00
|
|
|
</para>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
@mutex: a #GStaticMutex.
|
|
|
|
@Returns: TRUE, if the #GStaticMutex could be locked.
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### FUNCTION g_static_mutex_unlock ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
works like g_mutex_unlock(), but for a #GStaticMutex.
|
2000-09-06 00:04:49 +00:00
|
|
|
</para>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
@mutex: a #GStaticMutex.
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### FUNCTION g_static_mutex_get_mutex ##### -->
|
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
For some operations (like g_cond_wait()) you must have a #GMutex
|
|
|
|
instead of a #GStaticMutex. This function will return the
|
|
|
|
corresponding #GMutex for every #GStaticMutex.
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
@mutex: a #GStaticMutex.
|
|
|
|
@Returns: the corresponding #GMutex.
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
2001-01-30 14:16:56 +00:00
|
|
|
<!-- ##### FUNCTION g_static_mutex_free ##### -->
|
|
|
|
<para>
|
|
|
|
Releases all resources allocated to a #GStaticMutex. You don't have to
|
|
|
|
call this functions for a #GStaticMutex with an unbounded lifetime,
|
|
|
|
i.e. objects declared 'static', but if you have a #GStaticMutex as a
|
|
|
|
member of a structure and the structure is freed, you should also free
|
|
|
|
the #GStaticMutex.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
@mutex: a #GStaticMutex.
|
|
|
|
|
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
<!-- ##### MACRO G_LOCK_DEFINE ##### -->
|
2000-09-07 16:36:56 +00:00
|
|
|
|
|
|
|
<para>
|
|
|
|
The G_LOCK_* macros provide a convenient interface to #GStaticMutex
|
|
|
|
with the advantage that they will expand to nothing in programs
|
|
|
|
compiled against a thread-disabled GLib, saving code and memory
|
|
|
|
there. #G_LOCK_DEFINE defines a lock. It can occur, where variable
|
|
|
|
definitions may occur in programs, i.e. in the first block of a
|
|
|
|
function or outside of functions. The @name parameter will be mangled
|
|
|
|
to get the name of the #GStaticMutex. This means, that you can use
|
|
|
|
names of existing variables as the parameter, e.g. the name of the
|
|
|
|
variable you intent to protect with the lock. Look at our
|
|
|
|
give_me_next_number() example using the G_LOCK_* macros:
|
|
|
|
</para>
|
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-07 16:36:56 +00:00
|
|
|
<example>
|
|
|
|
<title>Using the G_LOCK_* convenience macros</title>
|
|
|
|
<programlisting>
|
|
|
|
G_LOCK_DEFINE (current_number);
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
int give_me_next_number ()
|
|
|
|
{
|
|
|
|
static int current_number = 0;
|
|
|
|
int ret_val;
|
|
|
|
|
|
|
|
G_LOCK (current_number);
|
|
|
|
ret_val = current_number = calc_next_number (current_number);
|
|
|
|
G_UNLOCK (current_number);
|
|
|
|
return ret_val;
|
|
|
|
}
|
|
|
|
</programlisting>
|
|
|
|
</example>
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
@name: the name of the lock.
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
<!-- ##### MACRO G_LOCK_DEFINE_STATIC ##### -->
|
2000-09-06 00:04:49 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
This works like #G_LOCK_DEFINE, but it creates a static object.
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
@name: the name of the lock.
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
<!-- ##### MACRO G_LOCK_EXTERN ##### -->
|
2000-09-06 00:04:49 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
This declares a lock, that is defined with #G_LOCK_DEFINE in another module.
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
@name: the name of the lock.
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
<!-- ##### MACRO G_LOCK ##### -->
|
2000-09-06 00:04:49 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
works like g_mutex_lock(), but for a lock defined with #G_LOCK_DEFINE.
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
@name: the name of the lock.
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
<!-- ##### MACRO G_TRYLOCK ##### -->
|
2000-09-06 00:04:49 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
works like g_mutex_trylock(), but for a lock defined with #G_LOCK_DEFINE.
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
@name: the name of the lock.
|
|
|
|
@Returns: TRUE, if the lock could be locked.
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
<!-- ##### MACRO G_UNLOCK ##### -->
|
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
works like g_mutex_unlock(), but for a lock defined with #G_LOCK_DEFINE.
|
2000-09-06 00:04:49 +00:00
|
|
|
</para>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
@name: the name of the lock.
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### STRUCT GStaticRecMutex ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-06 00:04:49 +00:00
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
@mutex:
|
|
|
|
@depth:
|
|
|
|
@owner:
|
|
|
|
|
|
|
|
<!-- ##### MACRO G_STATIC_REC_MUTEX_INIT ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
</para>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### FUNCTION g_static_rec_mutex_lock ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
|
|
|
|
|
|
|
</para>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
@mutex:
|
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### FUNCTION g_static_rec_mutex_trylock ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-06 00:04:49 +00:00
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
@mutex:
|
|
|
|
@Returns:
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### FUNCTION g_static_rec_mutex_unlock ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-06 00:04:49 +00:00
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
@mutex:
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### FUNCTION g_static_rec_mutex_lock_full ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-06 00:04:49 +00:00
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
@mutex:
|
|
|
|
@depth:
|
|
|
|
|
|
|
|
|
|
|
|
<!-- ##### FUNCTION g_static_rec_mutex_unlock_full ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
</para>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
@mutex:
|
|
|
|
@Returns:
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### STRUCT GStaticRWLock ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-06 00:04:49 +00:00
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
@mutex:
|
|
|
|
@read_cond:
|
|
|
|
@write_cond:
|
|
|
|
@read_counter:
|
|
|
|
@write:
|
|
|
|
@want_to_write:
|
|
|
|
|
|
|
|
<!-- ##### MACRO G_STATIC_RW_LOCK_INIT ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
</para>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### FUNCTION g_static_rw_lock_reader_lock ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-06 00:04:49 +00:00
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
@lock:
|
|
|
|
|
|
|
|
|
|
|
|
<!-- ##### FUNCTION g_static_rw_lock_reader_trylock ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
</para>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
@lock:
|
|
|
|
@Returns:
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### FUNCTION g_static_rw_lock_reader_unlock ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-06 00:04:49 +00:00
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
@lock:
|
|
|
|
|
|
|
|
|
|
|
|
<!-- ##### FUNCTION g_static_rw_lock_writer_lock ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-06 00:04:49 +00:00
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
@lock:
|
|
|
|
|
|
|
|
|
|
|
|
<!-- ##### FUNCTION g_static_rw_lock_writer_trylock ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
</para>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
@lock:
|
|
|
|
@Returns:
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### FUNCTION g_static_rw_lock_writer_unlock ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-06 00:04:49 +00:00
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
@lock:
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### FUNCTION g_static_rw_lock_free ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
</para>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
@lock:
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### STRUCT GCond ##### -->
|
2000-09-07 16:36:56 +00:00
|
|
|
|
|
|
|
<para>
|
|
|
|
The #GCond struct is an opaque data structure to represent a
|
|
|
|
condition. A #GCond is an object, that threads can block on, if they
|
|
|
|
find a certain condition to be false. If other threads change the
|
|
|
|
state of this condition they can signal the #GCond, such that the
|
|
|
|
waiting thread is woken up.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
<example>
|
|
|
|
<title>Using GCond to block a thread until a condition is satisfied</title>
|
|
|
|
<programlisting>
|
|
|
|
GCond* data_cond = NULL; /* Must be initialized somewhere */
|
|
|
|
GMutex* data_mutex = NULL; /* Must be initialized somewhere */
|
|
|
|
gpointer current_data = NULL;
|
|
|
|
|
|
|
|
void push_data (gpointer data)
|
|
|
|
{
|
|
|
|
g_mutex_lock (data_mutex);
|
|
|
|
current_data = data;
|
|
|
|
g_cond_signal (data_cond);
|
|
|
|
g_mutex_unlock (data_mutex);
|
|
|
|
}
|
|
|
|
|
|
|
|
gpointer pop_data ()
|
|
|
|
{
|
|
|
|
gpointer data;
|
|
|
|
|
|
|
|
g_mutex_lock (data_mutex);
|
|
|
|
while (!current_data)
|
|
|
|
g_cond_wait (data_cond, data_mutex);
|
|
|
|
data = current_data;
|
|
|
|
current_data = NULL;
|
|
|
|
g_mutex_unlock (data_mutex);
|
|
|
|
return data;
|
|
|
|
}
|
|
|
|
</programlisting>
|
|
|
|
</example>
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
Whenever a thread calls pop_data() now, it will wait until
|
|
|
|
current_data is non-NULL, i.e. until some other thread has called
|
|
|
|
push_data().
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<note>
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-07 16:36:56 +00:00
|
|
|
It is important to use the g_cond_wait() and g_cond_timed_wait()
|
|
|
|
functions only inside a loop, which checks for the condition to be
|
|
|
|
true as it is not guaranteed that the waiting thread will find it
|
|
|
|
fulfilled, even if the signaling thread left the condition
|
|
|
|
in that state. This is because another thread can have altered the
|
|
|
|
condition, before the waiting thread got the chance to be woken up,
|
|
|
|
even if the condition itself is protected by a #GMutex, like above.
|
|
|
|
</para>
|
|
|
|
</note>
|
2000-09-06 00:04:49 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
A #GCond should only be accessed via the following functions.
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<note>
|
|
|
|
<para>
|
|
|
|
All of the g_cond_* functions are actually macros. Apart from taking
|
|
|
|
the addresses of them, you can however use them as if they were functions.
|
|
|
|
</para>
|
|
|
|
</note>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
|
|
|
|
<!-- ##### FUNCTION g_cond_new ##### -->
|
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
Creates a new #GCond. This function will abort, if g_thread_init()
|
|
|
|
has not been called yet.
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
@Returns: a new #GCond.
|
2000-09-06 00:04:49 +00:00
|
|
|
|
|
|
|
|
|
|
|
<!-- ##### FUNCTION g_cond_signal ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-07 16:36:56 +00:00
|
|
|
If threads are waiting for @cond, exactly one of them is woken up. It
|
|
|
|
is good practice to hold the same lock as the waiting thread, while
|
|
|
|
calling this function, though not required.
|
|
|
|
</para>
|
2000-09-06 00:04:49 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
This function can also be used, if g_thread_init() has
|
|
|
|
not yet been called and will do nothing then.
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
@cond: a #GCond.
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### FUNCTION g_cond_broadcast ##### -->
|
2000-09-07 16:36:56 +00:00
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-07 16:36:56 +00:00
|
|
|
If threads are waiting for @cond, all of them are woken up. It is good
|
|
|
|
practice to lock the same mutex as the waiting threads, while calling
|
|
|
|
this function, though not required.
|
|
|
|
</para>
|
2000-09-06 00:04:49 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
This function can also be used, if g_thread_init() has
|
|
|
|
not yet been called and will do nothing then.
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
@cond: a #GCond.
|
2000-09-06 00:04:49 +00:00
|
|
|
|
|
|
|
|
|
|
|
<!-- ##### FUNCTION g_cond_wait ##### -->
|
2000-09-07 16:36:56 +00:00
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-07 16:36:56 +00:00
|
|
|
Waits until this thread is woken up on the #GCond. The #GMutex is
|
|
|
|
unlocked before falling asleep and locked again before resuming.
|
|
|
|
</para>
|
2000-09-06 00:04:49 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
This function can also be used, if g_thread_init() has not yet been
|
|
|
|
called and will immediately return then.
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
@cond: a #GCond.
|
|
|
|
@mutex: the #GMutex, that is currently locked.
|
2000-09-06 00:04:49 +00:00
|
|
|
|
|
|
|
|
|
|
|
<!-- ##### FUNCTION g_cond_timed_wait ##### -->
|
2000-09-07 16:36:56 +00:00
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-07 16:36:56 +00:00
|
|
|
Waits until this thread is woken up on the #GCond, but not longer than
|
|
|
|
until the time, that is specified by @abs_time. The #GMutex is
|
|
|
|
unlocked before falling asleep and locked again before resuming.
|
|
|
|
</para>
|
2000-09-06 00:04:49 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
If @abs_time is NULL, g_cond_timed_wait() acts like g_cond_wait().
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
This function can also be used, if g_thread_init() has not yet been
|
|
|
|
called and will immediately return TRUE then.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
@cond: a #GCond.
|
|
|
|
@mutex: the #GMutex, that is currently locked.
|
|
|
|
@abs_time: a #GTimeVal, determining the final time.
|
|
|
|
@Returns: TRUE, if the thread is woken up in time.
|
2000-09-06 00:04:49 +00:00
|
|
|
|
|
|
|
|
|
|
|
<!-- ##### FUNCTION g_cond_free ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
Destroys the #GCond.
|
2000-09-06 00:04:49 +00:00
|
|
|
</para>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
@cond: a #GCond.
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### STRUCT GPrivate ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-07 16:36:56 +00:00
|
|
|
The #GPrivate struct is an opaque data structure to represent a thread
|
|
|
|
private data key. Threads can thereby obtain and set a pointer, which
|
|
|
|
is private to the current thread. Take our give_me_next_number()
|
|
|
|
example from above. Now we don't want current_number to be shared
|
|
|
|
between the threads, but to be private to each thread. This can be
|
|
|
|
done as follows:
|
|
|
|
|
|
|
|
<example>
|
|
|
|
<title>Using GPrivate for per-thread data</title>
|
|
|
|
<programlisting>
|
|
|
|
GPrivate* current_number_key = NULL; /* Must be initialized somewhere */
|
|
|
|
/* with g_private_new (g_free); */
|
|
|
|
|
|
|
|
int give_me_next_number ()
|
|
|
|
{
|
|
|
|
int *current_number = g_private_get (current_number_key);
|
|
|
|
|
|
|
|
if (!current_number)
|
|
|
|
{
|
|
|
|
current_number = g_new (int,1);
|
|
|
|
*current_number = 0;
|
|
|
|
g_private_set (current_number_key, current_number);
|
|
|
|
}
|
|
|
|
*current_number = calc_next_number (*current_number);
|
|
|
|
return *current_number;
|
|
|
|
}
|
|
|
|
</programlisting>
|
|
|
|
</example>
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
Here the pointer belonging to the key current_number_key is read. If
|
|
|
|
it is NULL, it has not been set yet. Then get memory for an integer
|
|
|
|
value, assign this memory to the pointer and write the pointer
|
|
|
|
back. Now we have an integer value, that is private to the current
|
|
|
|
thread.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<para>
|
|
|
|
The #GPrivate struct should only be accessed via the following functions.
|
|
|
|
</para>
|
2000-09-06 00:04:49 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<note>
|
|
|
|
<para>
|
|
|
|
All of the g_private_* functions are actually macros. Apart from taking
|
|
|
|
the addresses of them, you can however use them as if they were functions.
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
2000-09-07 16:36:56 +00:00
|
|
|
</note>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
|
|
|
|
<!-- ##### FUNCTION g_private_new ##### -->
|
2000-09-07 16:36:56 +00:00
|
|
|
|
|
|
|
<para>
|
|
|
|
Creates a new #GPrivate. If @destructor is non-NULL, it is a pointer
|
|
|
|
to a destructor function. Whenever a thread ends and the corresponding
|
|
|
|
pointer keyed to this instance of #GPrivate is non-NULL, the
|
|
|
|
destructor is called with this pointer as the argument.
|
|
|
|
</para>
|
|
|
|
|
|
|
|
<note>
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-07 16:36:56 +00:00
|
|
|
The @destructor is working quite differently from @notify in
|
|
|
|
g_static_private_set().
|
|
|
|
</para>
|
|
|
|
</note>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<note>
|
|
|
|
<para>
|
|
|
|
A #GPrivate can not be destroyed. Reuse it instead, if you can to
|
|
|
|
avoid shortage.
|
2000-09-06 00:04:49 +00:00
|
|
|
</para>
|
2000-09-07 16:36:56 +00:00
|
|
|
</note>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<note>
|
|
|
|
<para>
|
|
|
|
This function will abort, if g_thread_init() has not been called yet.
|
|
|
|
</para>
|
|
|
|
</note>
|
|
|
|
|
|
|
|
@destructor: a function to handle the data keyed to #GPrivate, when a
|
|
|
|
thread ends.
|
2000-09-06 00:04:49 +00:00
|
|
|
@Returns:
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### FUNCTION g_private_get ##### -->
|
2000-09-07 16:36:56 +00:00
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-07 16:36:56 +00:00
|
|
|
Returns the pointer keyed to @private_key for the current thread. This
|
|
|
|
pointer is NULL, when g_private_set() hasn't been called for the
|
|
|
|
current @private_key and thread yet.
|
|
|
|
</para>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
This function can also be used, if g_thread_init() has not yet been
|
|
|
|
called and will return the value of @private_key casted to #gpointer then.
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
@private_key: a #GPrivate.
|
|
|
|
@Returns: the corresponding pointer.
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
<!-- ##### FUNCTION g_private_set ##### -->
|
2000-09-07 16:36:56 +00:00
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-07 16:36:56 +00:00
|
|
|
Sets the pointer keyed to @private_key for the current thread.
|
|
|
|
</para>
|
2000-09-06 00:04:49 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
This function can also be used, if g_thread_init() has not yet been
|
|
|
|
called and will set @private_key to @data casted to #GPrivate* then.
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
@private_key: a #GPrivate.
|
|
|
|
@data: the new pointer.
|
2000-09-06 00:04:49 +00:00
|
|
|
|
|
|
|
|
|
|
|
<!-- ##### STRUCT GStaticPrivate ##### -->
|
2000-09-07 16:36:56 +00:00
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-07 16:36:56 +00:00
|
|
|
A #GStaticPrivate works almost like a #GPrivate, but it has one
|
|
|
|
significant advantage. It doesn't need to be created at run-time like
|
|
|
|
a #GPrivate, but can be defined at compile-time. This is similar to
|
|
|
|
the difference between #GMutex and #GStaticMutex. Now look at our
|
|
|
|
give_me_next_number() example with #GStaticPrivate:
|
|
|
|
</para>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
<example>
|
|
|
|
<title>Using GStaticPrivate for per-thread data</title>
|
|
|
|
<programlisting>
|
|
|
|
int give_me_next_number ()
|
|
|
|
{
|
|
|
|
static GStaticPrivate current_number_key = G_STATIC_PRIVATE_INIT;
|
|
|
|
int *current_number = g_static_private_get (&current_number_key);
|
|
|
|
|
|
|
|
if (!current_number)
|
|
|
|
{
|
|
|
|
current_number = g_new (int,1);
|
|
|
|
*current_number = 0;
|
|
|
|
g_static_private_set (&current_number_key, current_number, g_free);
|
|
|
|
}
|
|
|
|
*current_number = calc_next_number (*current_number);
|
|
|
|
return *current_number;
|
|
|
|
}
|
|
|
|
</programlisting>
|
|
|
|
</example>
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
|
|
|
@index:
|
|
|
|
|
|
|
|
<!-- ##### MACRO G_STATIC_PRIVATE_INIT ##### -->
|
|
|
|
<para>
|
2000-09-07 16:36:56 +00:00
|
|
|
Every #GStaticPrivate must be initialized with this macro, before it can
|
|
|
|
be used.
|
|
|
|
</para>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
<informalexample>
|
|
|
|
<programlisting>
|
|
|
|
GStaticPrivate my_private = G_STATIC_PRIVATE_INIT;
|
|
|
|
</programlisting>
|
|
|
|
</informalexample>
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<!-- ##### FUNCTION g_static_private_get ##### -->
|
|
|
|
<para>
|
2000-09-07 16:36:56 +00:00
|
|
|
Works like g_private_get() only for a #GStaticPrivate.
|
|
|
|
</para>
|
2000-09-06 00:04:49 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
This function also works, if g_thread_init() has not yet been called.
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
@private_key: a #GStaticPrivate.
|
|
|
|
@Returns: the corresponding pointer.
|
2000-09-06 00:04:49 +00:00
|
|
|
|
|
|
|
|
|
|
|
<!-- ##### FUNCTION g_static_private_get_for_thread ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-06 00:04:49 +00:00
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
@private_key:
|
|
|
|
@thread:
|
|
|
|
@Returns:
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|
|
|
|
<!-- ##### FUNCTION g_static_private_set ##### -->
|
|
|
|
<para>
|
2000-09-07 16:36:56 +00:00
|
|
|
Sets the pointer keyed to @private_key for the current thread and the
|
|
|
|
function @notify to be called with that pointer (NULL or non-NULL),
|
|
|
|
whenever the pointer is set again or whenever the current thread ends.
|
|
|
|
</para>
|
1999-08-16 17:58:30 +00:00
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<para>
|
|
|
|
This function also works, if g_thread_init() has not yet been
|
|
|
|
called. If g_thread_init() is called later, the @data keyed to
|
|
|
|
@private_key will be inherited only by the main thread, i.e. the one that
|
|
|
|
called g_thread_init().
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-07 16:36:56 +00:00
|
|
|
<note>
|
|
|
|
<para>
|
|
|
|
The @notify is working quite differently from @destructor in
|
|
|
|
g_private_new().
|
|
|
|
</para>
|
|
|
|
</note>
|
|
|
|
|
|
|
|
@private_key: a #GStaticPrivate.
|
|
|
|
@data: the new pointer.
|
|
|
|
@notify: a function to be called with the pointer, whenever the
|
|
|
|
current thread ends or sets this pointer again.
|
2000-09-06 00:04:49 +00:00
|
|
|
|
|
|
|
|
|
|
|
<!-- ##### FUNCTION g_static_private_set_for_thread ##### -->
|
1999-08-16 17:58:30 +00:00
|
|
|
<para>
|
2000-09-06 00:04:49 +00:00
|
|
|
|
1999-08-16 17:58:30 +00:00
|
|
|
</para>
|
|
|
|
|
2000-09-06 00:04:49 +00:00
|
|
|
@private_key:
|
|
|
|
@thread:
|
|
|
|
@data:
|
|
|
|
@notify:
|
1999-08-16 17:58:30 +00:00
|
|
|
|
|
|
|
|