Look for nanosleep function.
[platform/upstream/glib.git] / docs / reference / glib / tmpl / threads.sgml
index dc1c245..80f2c71 100644 (file)
 <!-- ##### SECTION Title ##### -->
+
 Threads
 
 <!-- ##### SECTION Short_Description ##### -->
 
+thread abstraction; including threads, different mutexes, conditions
+and thread private data.
 
 <!-- ##### SECTION Long_Description ##### -->
-<para>
 
+<para>
+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 explicitly forced by
+the programmer through synchronization primitives.
 </para>
 
+<para>
+The aim of the thread related functions in GLib is to provide a
+portable means for writing multi-threaded software. There are
+primitives for mutexes to protect the access to portions of memory
+(#GMutex, #GStaticMutex, #G_LOCK_DEFINE, #GStaticRecMutex and
+#GStaticRWLock), 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). Last but definitely not least there are
+primitives to portably create and manage threads (#GThread).
+</para>
 
 <!-- ##### SECTION See_Also ##### -->
 <para>
+<variablelist>
 
-</para>
+<varlistentry>
+<term>#GThreadPool</term>
+<listitem><para>Thread pools.</para></listitem>
+</varlistentry>
 
+<varlistentry>
+<term>#GAsyncQueue</term>
+<listitem><para>Send asynchronous messages between threads.</para></listitem>
+</varlistentry>
+
+</variablelist>
+</para>
 
 <!-- ##### MACRO G_THREADS_ENABLED ##### -->
-<para>
 
+<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 multi-thread
+safe. It isn't and cannot be, if #G_THREADS_ENABLED is not defined.
 </para>
 
 
 
 <!-- ##### MACRO G_THREADS_IMPL_POSIX ##### -->
-<para>
 
+<para>
+This macro is defined, if POSIX style threads are used.
 </para>
 
 
 
 <!-- ##### MACRO G_THREADS_IMPL_SOLARIS ##### -->
-<para>
 
+<para>
+This macro is defined, if the Solaris thread system is used.
 </para>
 
 
 
 <!-- ##### MACRO G_THREADS_IMPL_NONE ##### -->
-<para>
 
+<para>
+This macro is defined, if no thread implementation is used. You can
+however provide one to g_thread_init() to make GLib multi-thread safe.
 </para>
 
 
 
 <!-- ##### MACRO G_THREAD_ERROR ##### -->
 <para>
-
+The error domain of the GLib thread subsystem.
 </para>
 
 
 
 <!-- ##### ENUM GThreadError ##### -->
 <para>
-
+Possible errors of thread related functions.
 </para>
 
-@G_THREAD_ERROR_AGAIN: 
+@G_THREAD_ERROR_AGAIN: a thread couldn't be created due to resource
+shortage. Try again later.
 
 <!-- ##### STRUCT GThreadFunctions ##### -->
+
 <para>
+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>
 
+<note>
+<para>
+This struct should only be used, if you know, what you are doing.
 </para>
+</note>
 
 @mutex_new: 
 @mutex_lock: 
@@ -85,247 +139,754 @@ Threads
 @thread_self: 
 
 <!-- ##### FUNCTION g_thread_init ##### -->
+
+<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
+call-back from GLib. Also no mutexes may be currently locked, while
+calling g_thread_init().
+</para>
+</note>
 
+<para>
+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>
 
-@vtable: 
+<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>
+
+<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.
+</para>
+</note>
+
+@vtable: a function table of type #GThreadFunctions, that provides the
+entry points to the thread system to be used
 
 
 <!-- ##### FUNCTION g_thread_supported ##### -->
 <para>
+This function returns, whether the thread system is initialized or
+not.
+</para>
 
+<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.
 </para>
+</note>
 
-@Returns: 
+@Returns: TRUE, if the thread system is initialized
 
 
 <!-- ##### USER_FUNCTION GThreadFunc ##### -->
 <para>
-
+Specifies the type of the @func functions passed to
+g_thread_create() or g_thread_create_full().
 </para>
 
-@value: 
+@data: data passed to the thread
+@Returns: the return value of the thread, which will be returned by
+g_thread_join()
 
 
 <!-- ##### ENUM GThreadPriority ##### -->
 <para>
+Specifies the priority of a thread. 
+</para>
 
+<note>
+<para>
+It is not guaranteed, that threads with different priorities really
+behave accordingly. On some systems (e.g. Linux) only root can increase
+priorities. On other systems (e.g. Solaris) there doesn't seem to be
+different scheduling for different priorities. All in all try to avoid
+being dependent on priorities.
 </para>
+</note>
 
-@G_THREAD_PRIORITY_LOW: 
-@G_THREAD_PRIORITY_NORMAL: 
-@G_THREAD_PRIORITY_HIGH: 
-@G_THREAD_PRIORITY_URGENT: 
+@G_THREAD_PRIORITY_LOW: a priority lower than normal
+@G_THREAD_PRIORITY_NORMAL: the default priority
+@G_THREAD_PRIORITY_HIGH: a priority higher than normal
+@G_THREAD_PRIORITY_URGENT: the highest priority
 
 <!-- ##### STRUCT GThread ##### -->
 <para>
+The #GThread struct represents a running thread. It has three public
+read-only members, but the underlying struct is bigger, so you must
+not copy this struct.
+</para>
 
+<note>
+<para>
+Resources for a joinable thread are not fully released until
+g_thread_join() is called for that thread.
 </para>
+</note>
 
-@priority: 
-@bound: 
-@joinable: 
+@func: the function executing in that thread
+@data: the argument to the function
+@joinable: is this thread joinable?
+@priority: the priority of the thread
 
 <!-- ##### FUNCTION g_thread_create ##### -->
 <para>
+This function creates a new thread with the priority @priority.
+</para>
+
+<para>
+If @joinable is #TRUE, you can wait for this threads termination
+calling g_thread_wait(). Otherwise the thread will just disappear, when
+ready. 
+</para>
+
+<para>
+The new thread executes the function @func with the argument
+@data. If the thread was created successfully, it is returned.
+</para>
 
+<para>
+@error can be NULL to ignore errors, or non-NULL to report errors. The
+error is set, if and only if the function returns #NULL.
 </para>
 
-@thread_func: 
-@arg: 
-@stack_size: 
-@joinable: 
-@bound: 
-@priority: 
-@error: 
-@Returns: 
+@func: a function to execute in the new thread
+@data: an argument to supply to the new thread
+@joinable: should this thread be joinable?
+@error: return location for error.
+@Returns: the new #GThread on success
 
 
-<!-- ##### FUNCTION g_thread_self ##### -->
+<!-- ##### FUNCTION g_thread_create_full ##### -->
 <para>
+This function creates a new thread with the priority @priority. The
+stack gets the size @stack_size or the default value for the current
+platform, if @stack_size is 0.
+</para>
 
+<para>
+If @joinable is #TRUE, you can wait for this threads termination
+calling g_thread_wait(). Otherwise the thread will just disappear, when
+ready. If @bound is #TRUE, this thread will be scheduled in the system
+scope, otherwise the implementation is free to do scheduling in the
+process scope. The first variant is more expensive resource-wise, but
+generally faster. On some systems (e.g. Linux) all threads are bound.
 </para>
 
-@Returns: 
+<para>
+The new thread executes the function @func with the argument
+@data. If the thread was created successfully, it is returned.
+</para>
 
+<para>
+@error can be NULL to ignore errors, or non-NULL to report errors. The
+error is set, if and only if the function returns #NULL.
+</para>
 
-<!-- ##### FUNCTION g_thread_join ##### -->
+<note>
 <para>
+It is not guaranteed, that threads with different priorities really
+behave accordingly. On some systems (e.g. Linux) only root can increase
+priorities. On other systems (e.g. Solaris) there doesn't seem to be
+different scheduling for different priorities. All in all try to avoid
+being dependent on priorities. Use %G_THREAD_PRIORITY_NORMAL here as a
+default.
+</para>
+</note>
 
+<note>
+<para>
+Only use g_thread_create_full(), when you really can't use
+g_thread_create() instead. g_thread_create() does not take
+@stack_size, @bound and @priority as arguments, as they should only be
+used for cases, where it is inevitable. 
 </para>
+</note>
 
-@thread: 
+@func: a function to execute in the new thread
+@data: an argument to supply to the new thread
+@stack_size: a stack size for the new thread
+@joinable: should this thread be joinable?
+@bound: should this thread be bound to a system thread?
+@priority: a priority for the thread
+@error: return location for error.
+@Returns: the new #GThread on success
+
+
+<!-- ##### FUNCTION g_thread_self ##### -->
+<para>
+This functions returns the #GThread corresponding to the calling thread.
+</para>
+
+@Returns: the current thread
+
+
+<!-- ##### FUNCTION g_thread_join ##### -->
+<para>
+Waits until @thread finishes, i.e. the function @func, as given
+to g_thread_create, returns or g_thread_exit() is called by
+@thread. All resources of @thread including the #GThread struct are
+released. @thread must have been created with @joinable=#TRUE in
+g_thread_create(). The value returned by @func or given to
+g_thread_exit() by @thread is returned by this function.
+</para>
+
+@thread: a #GThread to be waited for
+@Returns: the return value of the thread
 
 
 <!-- ##### FUNCTION g_thread_set_priority ##### -->
 <para>
+Change the priority of @thread to @priority.
+</para>
+
+<note>
+<para>
+It is not guaranteed, that threads with different priorities really
+behave accordingly. On some systems (e.g. Linux) only root can increase
+priorities. On other systems (e.g. Solaris) there doesn't seem to be
+different scheduling for different priorities. All in all try to avoid
+being dependent on priorities.
+</para>
+</note>
 
+@thread: a #GThread
+@priority: a new priority for @thread
+
+
+<!-- ##### FUNCTION g_thread_yield ##### -->
+<para>
+Give way to other threads waiting to be scheduled. 
+</para>
+
+<para>
+This function is often used as a method to make busy wait less
+evil. But in most cases, you will encounter, there are better methods
+to do that. So in general you shouldn't use that function.
 </para>
 
-@thread: 
-@priority: 
 
 
-<!-- ##### MACRO g_thread_yield ##### -->
+<!-- ##### FUNCTION g_thread_exit ##### -->
 <para>
+Exit the current thread. If another thread is waiting for that thread
+using g_thread_join() and the current thread is joinable, the waiting
+thread will be woken up and getting @retval as the return value of
+g_thread_join(). If the current thread is not joinable, @retval is
+ignored. Calling
+</para>
 
+<para>
+<informalexample>
+<programlisting>
+g_thread_join (retval);
+</programlisting>
+</informalexample>
 </para>
 
+<para>
+is equivalent to calling 
+</para>
 
+<para>
+<informalexample>
+<programlisting>
+return retval;
+</programlisting>
+</informalexample>
+</para>
 
-<!-- ##### MACRO g_thread_exit ##### -->
 <para>
+in the function @func, as given to g_thread_create().
+</para>
 
+<note>
+<para>
+Never call g_thread_exit from within a thread of a #GThreadPool, as
+that will mess up the bookkeeping and lead to funny and unwanted
+results.
 </para>
+</note>
 
+@retval: the return value of this thread
 
 
 <!-- ##### STRUCT GMutex ##### -->
+
+<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 multi-threaded
+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
+constructing the mutex and this code cannot work reliable. So please do
+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>
+
+<para>
+#GStaticMutex provides a simpler and safer way of doing this.
+</para>
+
 <para>
+If you want to use a mutex, but your code should also work without
+calling g_thread_init() first, you can not use a #GMutex, as
+g_mutex_new() requires that. Use a #GStaticMutex instead.
+</para>
 
+<para>
+A #GMutex should only be accessed via the following functions.
 </para>
 
+<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>
+
 
 <!-- ##### FUNCTION g_mutex_new ##### -->
+
 <para>
+Creates a new #GMutex. 
+</para>
 
+<note>
+<para>
+This function will abort, if g_thread_init() has not been called yet.
 </para>
+</note>
 
-@Returns: 
+@Returns: a new #GMutex
 
 
 <!-- ##### FUNCTION g_mutex_lock ##### -->
+
 <para>
+Locks @mutex. If @mutex is already locked by another thread, the
+current thread will block until @mutex is unlocked by the other
+thread.
+</para>
 
+<para>
+This function can also be used, if g_thread_init() has not yet been
+called and will do nothing then.
 </para>
 
-@mutex: 
+<note>
+<para>
+#GMutex is not recursive, i.e. a thread will deadlock, if it already
+has locked @mutex while calling g_mutex_lock(). Use
+#GStaticRecMutex instead, if you need recursive mutexes.
+</para>
+</note>
+
+@mutex: a #GMutex
 
 
 <!-- ##### FUNCTION g_mutex_trylock ##### -->
+
 <para>
+Tries to lock @mutex. If @mutex is already locked by another
+thread, it immediately returns FALSE. Otherwise it locks @mutex
+and returns TRUE.
+</para>
 
+<para>
+This function can also be used, if g_thread_init() has not yet been
+called and will immediately return TRUE then.
 </para>
 
-@mutex: 
-@Returns: 
+<note>
+<para>
+#GMutex is not recursive, i.e. g_mutex_trylock() will return FALSE,
+if the current thread already has locked @mutex. Use
+#GStaticRecMutex instead, if you need recursive mutexes.
+</para>
+</note>
+
+@mutex: a #GMutex
+@Returns: TRUE, if @mutex could be locked
 
 
 <!-- ##### FUNCTION g_mutex_unlock ##### -->
+
 <para>
+Unlocks @mutex. If another thread is blocked in a g_mutex_lock() call
+for @mutex, it will be woken and can lock @mutex itself.
+</para>
 
+<para>
+This function can also be used, if g_thread_init() has not yet been
+called and will do nothing then.
 </para>
 
-@mutex: 
+@mutex: a #GMutex
 
 
 <!-- ##### FUNCTION g_mutex_free ##### -->
-<para>
 
+<para>
+Destroys @mutex.
 </para>
 
-@mutex: 
+@mutex: a #GMutex
 
 
 <!-- ##### STRUCT GStaticMutex ##### -->
+
+<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>
+
 <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 (&amp;mutex);
+    ret_val = current_number = calc_next_number (current_number); 
+    g_static_mutex_unlock (&amp;mutex);
+    return ret_val;
+  }
+</programlisting>
+</example>
 </para>
 
+<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. It
+must be initialized with g_static_mutex_init() before using it and
+freed with with g_static_mutex_free() when not needed anymore to free
+up any allocated recourses.
+</para>
+
+<para>
+Even though #GStaticMutex is not opaque, it should only be used with
+the following functions, as it is defined differently on different
+platforms.
+</para>
+
+<para>
+All of the g_static_mutex_* functions can also be used, if
+g_thread_init() has not yet been called.
+</para>
+
+<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>
+
 
 <!-- ##### MACRO G_STATIC_MUTEX_INIT ##### -->
+
 <para>
+A #GStaticMutex must be initialized with this macro, before it can be
+used. This macro can used be to initialize a variable, but it cannot
+be assigned to a variable. In that case you have to use
+g_static_mutex_init().
+</para>
 
+<para>
+<informalexample>
+<programlisting>
+GStaticMutex my_mutex = G_STATIC_MUTEX_INIT;
+</programlisting>
+</informalexample>
 </para>
 
 
 
-<!-- ##### FUNCTION g_static_mutex_lock ##### -->
+<!-- ##### FUNCTION g_static_mutex_init ##### -->
 <para>
+Initializes @mutex. Alternatively you can initialize it with
+#G_STATIC_MUTEX_INIT.
+</para>
+
+@mutex: a #GStaticMutex to be initialized
+
 
+<!-- ##### FUNCTION g_static_mutex_lock ##### -->
+<para>
+Works like g_mutex_lock(), but for a #GStaticMutex.
 </para>
 
-@mutex: 
+@mutex: a #GStaticMutex
 
 
 <!-- ##### FUNCTION g_static_mutex_trylock ##### -->
-<para>
 
+<para>
+Works like g_mutex_trylock(), but for a #GStaticMutex.
 </para>
 
-@mutex: 
-@Returns: 
+@mutex: a #GStaticMutex
+@Returns: TRUE, if the #GStaticMutex could be locked
 
 
 <!-- ##### FUNCTION g_static_mutex_unlock ##### -->
-<para>
 
+<para>
+Works like g_mutex_unlock(), but for a #GStaticMutex.
 </para>
 
-@mutex: 
+@mutex: a #GStaticMutex
 
 
 <!-- ##### FUNCTION g_static_mutex_get_mutex ##### -->
+
+<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 @mutex.
+</para>
+
+@mutex: a #GStaticMutex
+@Returns: the #GMutex corresponding to @mutex
+
+
+<!-- ##### FUNCTION g_static_mutex_free ##### -->
 <para>
+Releases all resources allocated to @mutex. 
+</para>
 
+<para>
+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: 
-@Returns: 
+@mutex: a #GStaticMutex to be freed
 
 
 <!-- ##### MACRO G_LOCK_DEFINE ##### -->
+
 <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 appear, where variable
+definitions may appear 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>
 
+<para>
+<example>
+<title>Using the G_LOCK_* convenience macros</title>
+<programlisting>
+G_LOCK_DEFINE (current_number);
+
+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>
 </para>
 
-@name: 
+@name: the name of the lock
 
 
 <!-- ##### MACRO G_LOCK_DEFINE_STATIC ##### -->
-<para>
 
+<para>
+This works like #G_LOCK_DEFINE, but it creates a static object.
 </para>
 
-@name: 
+@name: the name of the lock
 
 
 <!-- ##### MACRO G_LOCK_EXTERN ##### -->
-<para>
 
+<para>
+This declares a lock, that is defined with #G_LOCK_DEFINE in another module.
 </para>
 
-@name: 
+@name: the name of the lock
 
 
 <!-- ##### MACRO G_LOCK ##### -->
-<para>
 
+<para>
+Works like g_mutex_lock(), but for a lock defined with #G_LOCK_DEFINE.
 </para>
 
-@name: 
+@name: the name of the lock
 
 
 <!-- ##### MACRO G_TRYLOCK ##### -->
-<para>
 
+<para>
+Works like g_mutex_trylock(), but for a lock defined with #G_LOCK_DEFINE.
 </para>
 
-@name: 
+@name: the name of the lock
+@Returns: TRUE, if the lock could be locked
 
 
 <!-- ##### MACRO G_UNLOCK ##### -->
-<para>
 
+<para>
+Works like g_mutex_unlock(), but for a lock defined with #G_LOCK_DEFINE.
 </para>
 
-@name: 
+@name: the name of the lock
 
 
 <!-- ##### STRUCT GStaticRecMutex ##### -->
 <para>
+A #GStaticRecMutex works like a #GStaticMutex, but it can be locked
+multiple times by one thread. If you enter it n times, however, you
+have to unlock it n times again to let other threads lock it. An
+exception is the function g_static_rec_mutex_unlock_full(), that
+allows you to unlock a #GStaticRecMutex completely returning the depth,
+i.e. the number of times this mutex was locked. The depth can later be
+used to restore the state by calling g_static_rec_mutex_lock_full().
+</para>
+
+<para>
+Even though #GStaticRecMutex is not opaque, it should only be used with
+the following functions.
+</para>
 
+<para>
+All of the g_static_rec_mutex_* functions can also be used, if
+g_thread_init() has not been called.
 </para>
 
 @mutex: 
@@ -334,59 +895,198 @@ Threads
 
 <!-- ##### MACRO G_STATIC_REC_MUTEX_INIT ##### -->
 <para>
+A #GStaticRecMutex must be initialized with this macro, before it can
+be used. This macro can used be to initialize a variable, but it
+cannot be assigned to a variable. In that case you have to use
+g_static_rec_mutex_init().
+</para>
 
+<para>
+<informalexample>
+<programlisting>
+GStaticRecMutex my_mutex = G_STATIC_REC_MUTEX_INIT;
+</programlisting>
+</informalexample>
 </para>
 
 
 
-<!-- ##### FUNCTION g_static_rec_mutex_lock ##### -->
+<!-- ##### FUNCTION g_static_rec_mutex_init ##### -->
 <para>
+A #GStaticRecMutex must be initialized with this function, before it
+can be used. Alternatively you can initialize it with
+#G_STATIC_REC_MUTEX_INIT.
+</para>
+
+@mutex: a #GStaticRecMutex to be initialized
 
+
+<!-- ##### FUNCTION g_static_rec_mutex_lock ##### -->
+<para>
+Locks @mutex. If @mutex is already locked by another thread, the
+current thread will block until @mutex is unlocked by the other
+thread. If @mutex is already locked by the calling thread, this
+functions increases the depth of @mutex and returns immediately.
 </para>
 
-@mutex: 
+@mutex: a #GStaticRecMutex to lock
 
 
 <!-- ##### FUNCTION g_static_rec_mutex_trylock ##### -->
 <para>
-
+Tries to lock @mutex. If @mutex is already locked by another thread,
+it immediately returns #FALSE. Otherwise it locks @mutex and returns
+#TRUE. If @mutex is already locked by the calling thread, this
+functions increases the depth of @mutex and immediately  returns #TRUE.
 </para>
 
-@mutex: 
-@Returns: 
+@mutex: a #GStaticRecMutex to lock
+@Returns: TRUE, if @mutex could be locked
 
 
 <!-- ##### FUNCTION g_static_rec_mutex_unlock ##### -->
 <para>
-
+Unlocks @mutex. Another threads can, however, only lock @mutex when it
+has been unlocked as many times, as it had been locked before. If
+@mutex is completely unlocked and another thread is blocked in a
+g_static_rec_mutex_lock() call for @mutex, it will be woken and can
+lock @mutex itself.
 </para>
 
-@mutex: 
+@mutex: a #GStaticRecMutex to unlock
 
 
 <!-- ##### FUNCTION g_static_rec_mutex_lock_full ##### -->
 <para>
-
+Works like calling g_static_rec_mutex_lock() for @mutex n times.
 </para>
 
-@mutex: 
-@depth: 
+@mutex: a #GStaticRecMutex to lock
+@depth: number of times this mutex has to be unlocked to be completely unlocked
 
 
 <!-- ##### FUNCTION g_static_rec_mutex_unlock_full ##### -->
 <para>
+Completely unlocks @mutex. If another thread is blocked in a
+g_static_rec_mutex_lock() call for @mutex, it will be woken and can
+lock @mutex itself. This function returns the number of times, that
+@mutex has been locked by the current thread. To restore the state
+before the call to g_static_rec_mutex_unlock_full() you can call
+g_static_rec_mutex_lock_full() with the depth returned by this
+function.
+</para>
+
+@mutex: a #GStaticRecMutex to completely unlock
+@Returns: number of times @mutex has been locked by the current thread
+
 
+<!-- ##### FUNCTION g_static_rec_mutex_free ##### -->
+<para>
+Releases all resources allocated to a #GStaticRecMutex.
 </para>
 
-@mutex: 
-@Returns: 
+<para>
+You don't have to call this functions for a #GStaticRecMutex with an
+unbounded lifetime, i.e. objects declared 'static', but if you have a
+#GStaticRecMutex as a member of a structure and the structure is
+freed, you should also free the #GStaticRecMutex.
+</para>
+
+@mutex: a #GStaticRecMutex to be freed
 
 
 <!-- ##### STRUCT GStaticRWLock ##### -->
 <para>
+The #GStaticRWLock struct represents a read-write lock. A read-write
+lock can be used for protecting data, that some portions of code only
+read from, while others also write. In such situations it is
+desirable, that several readers can read at once, whereas of course
+only one writer may write at a time. Take a look at the following
+example:
+
+<example>
+<title>An array with access functions</title>
+<programlisting>
+  GStaticRWLock rwlock = G_STATIC_RW_LOCK_INIT;
+
+  GPtrArray *array;
+
+  gpointer my_array_get (guint index)
+  {
+    gpointer retval = NULL;
+
+    if (!array)
+      return NULL;
 
+    g_static_rw_lock_reader_lock (&amp;rwlock);
+
+    if (index < array->len)
+      retval = g_ptr_array_index (array, index);
+
+    g_static_rw_lock_reader_unlock (&amp;rwlock);
+
+    return retval;
+  }
+
+  void my_array_set (guint index, gpointer data)
+  {
+    g_static_rw_lock_writer_lock (&amp;rwlock);
+
+    if (!array)
+      array = g_ptr_array_new ();
+
+    if (index >= array->len)
+      g_ptr_array_set_size (array, index+1);
+
+    g_ptr_array_index (array, index) = data; 
+
+    g_static_rw_lock_writer_unlock (&amp;rwlock);
+  }
+</programlisting>
+</example>
+</para>
+
+<para>
+This example shows an array, which can be accessed by many readers
+(the my_array_get function) simultaneously, whereas the writers (the
+my_array_set function) only will be allowed once a time and only if no
+readers currently access the array. This is because of the potentially
+dangerous resizing of the array. Using that functions is fully
+multi-thread safe now. 
 </para>
 
+<para>
+Most of the time the writers should have precedence of readers. That
+means for this implementation, that as soon as a writer wants to lock
+the data, no other reader is allowed to lock the data, whereas of
+course the readers, that already have locked the data are allowed to
+finish their operation. As soon as the last reader unlocks the data,
+the writer will lock it.
+</para>
+
+<para>
+Even though #GStaticRWLock is not opaque, it should only be used with
+the following functions.
+</para>
+
+<para>
+All of the g_static_rw_lock_* functions can also be used, if
+g_thread_init() has not been called.
+</para>
+
+<note>
+<para>
+A read-write lock has a higher overhead as a mutex. For example both
+g_static_rw_lock_reader_lock() and g_static_rw_lock_reader_unlock()
+has to lock and unlock a #GStaticMutex, so it takes at least twice the
+time to lock and unlock a #GStaticRWLock than to lock and unlock a
+#GStaticMutex. So only data structures, that are accessed by multiple
+readers, which keep the lock for a considerable time justify a
+#GStaticRWLock. The above example most probably would fare better with
+a #GStaticMutex.
+</para>
+</note>
+
 @mutex: 
 @read_cond: 
 @write_cond: 
@@ -396,211 +1096,525 @@ Threads
 
 <!-- ##### MACRO G_STATIC_RW_LOCK_INIT ##### -->
 <para>
+A #GStaticRWLock must be initialized with this macro, before it can
+be used. This macro can used be to initialize a variable, but it
+cannot be assigned to a variable. In that case you have to use
+g_static_rw_lock_init().
+</para>
 
+<para>
+<informalexample>
+<programlisting>
+GStaticRWLock my_lock = G_STATIC_RW_LOCK_INIT;
+</programlisting>
+</informalexample>
 </para>
 
 
 
+<!-- ##### FUNCTION g_static_rw_lock_init ##### -->
+<para>
+A #GStaticRWLock must be initialized with this function, before it can
+be used. Alternatively you can initialize it with
+#G_STATIC_RW_LOCK_INIT.
+</para>
+
+@lock: a #GStaticRWLock to be initialized
+
+
 <!-- ##### FUNCTION g_static_rw_lock_reader_lock ##### -->
 <para>
+Locks @lock for reading. There may be unlimited concurrent locks for
+reading of a #GStaticRWLock at the same time.  If @lock is already
+locked for writing by another thread or if another thread is already
+waiting to lock @lock for writing, this function will block until
+@lock is unlocked by the other writing thread and no other writing
+threads want to lock @lock. This lock has to be unlocked by
+g_static_rw_lock_reader_unlock().
+</para>
 
+<para>
+#GStaticRWLock in general is not recursive, but as there may be
+unlimited concurrent locks for reading, it effectively is for
+recursive for reading, but for reading only. Locking for writing after
+locking for reading will deadlock, the same holds true for the
+opposite order.
 </para>
 
-@lock: 
+@lock: a #GStaticRWLock to lock for reading
 
 
 <!-- ##### FUNCTION g_static_rw_lock_reader_trylock ##### -->
 <para>
-
+Tries to lock @lock for reading. If @lock is already locked for
+writing by another thread or if another thread is already waiting to
+lock @lock for writing, it immediately returns #FALSE. Otherwise it
+locks @lock for reading and returns TRUE. This lock has to be unlocked
+by g_static_rw_lock_reader_unlock().
 </para>
 
-@lock: 
-@Returns: 
+@lock: a #GStaticRWLock to lock for reading
+@Returns: TRUE, if @lock could be locked for reading
 
 
 <!-- ##### FUNCTION g_static_rw_lock_reader_unlock ##### -->
 <para>
-
+Unlocks @lock. If a thread waits to lock @lock for writing and all
+locks for reading have been unlocked, the waiting thread is woken up
+and can lock @lock for writing.
 </para>
 
-@lock: 
+@lock: a #GStaticRWLock to unlock after reading
 
 
 <!-- ##### FUNCTION g_static_rw_lock_writer_lock ##### -->
 <para>
-
+Locks @lock for writing. If @lock is already locked for writing or
+reading by other threads, this function will block until @lock is
+completely unlocked and then lock @lock for writing. While this
+functions waits to lock @lock, no other thread can lock @lock for
+reading. When @lock is locked for writing, no other thread can lock
+@lock (neither for reading nor writing). This lock has to be unlocked
+by g_static_rw_lock_writer_unlock().
 </para>
 
-@lock: 
+@lock: a #GStaticRWLock to lock for writing
 
 
 <!-- ##### FUNCTION g_static_rw_lock_writer_trylock ##### -->
 <para>
-
+Tries to lock @lock for writing. If @lock is already locked (for
+either reading or writing) by another thread, it immediately returns
+#FALSE. Otherwise it locks @lock for writing and returns TRUE. This
+lock has to be unlocked by g_static_rw_lock_writer_unlock().
 </para>
 
-@lock: 
-@Returns: 
+@lock: a #GStaticRWLock to lock for writing
+@Returns: TRUE, if @lock could be locked for writing
 
 
 <!-- ##### FUNCTION g_static_rw_lock_writer_unlock ##### -->
 <para>
-
+Unlocks @lock. If a thread waits to lock @lock for writing and all
+locks for reading have been unlocked, the waiting thread is woken up
+and can lock @lock for writing. If no thread waits to lock @lock for
+writing and threads wait to lock @lock for reading, the waiting
+threads are woken up and can lock @lock for reading.
 </para>
 
-@lock: 
+@lock: a #GStaticRWLock to unlock after writing
 
 
 <!-- ##### FUNCTION g_static_rw_lock_free ##### -->
 <para>
+Releases all resources allocated to @lock. 
+</para>
 
+<para>
+You don't have to call this functions for a #GStaticRWLock with an
+unbounded lifetime, i.e. objects declared 'static', but if you have a
+#GStaticRWLock as a member of a structure and the structure is freed,
+you should also free the #GStaticRWLock.
 </para>
 
-@lock: 
+@lock: a #GStaticRWLock to be freed
 
 
 <!-- ##### STRUCT GCond ##### -->
+
+<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>
+<para>
+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>
 
-<!-- ##### FUNCTION g_cond_new ##### -->
 <para>
+A #GCond should only be accessed via the following functions.
+</para>
+
+<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>
+
 
+<!-- ##### FUNCTION g_cond_new ##### -->
+
+<para>
+Creates a new #GCond. This function will abort, if g_thread_init()
+has not been called yet.
 </para>
 
-@Returns: 
+@Returns: a new #GCond
 
 
 <!-- ##### FUNCTION g_cond_signal ##### -->
 <para>
+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>
 
+<para>
+This function can also be used, if g_thread_init() has
+not yet been called and will do nothing then.
 </para>
 
-@cond: 
+@cond: a #GCond
 
 
 <!-- ##### FUNCTION g_cond_broadcast ##### -->
+
 <para>
+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>
 
+<para>
+This function can also be used, if g_thread_init() has
+not yet been called and will do nothing then.
 </para>
 
-@cond: 
+@cond: a #GCond
 
 
 <!-- ##### FUNCTION g_cond_wait ##### -->
+
 <para>
+Waits until this thread is woken up on @cond. The @mutex is unlocked
+before falling asleep and locked again before resuming.
+</para>
 
+<para>
+This function can also be used, if g_thread_init() has not yet been
+called and will immediately return then.
 </para>
 
-@cond: 
-@mutex: 
+@cond: a #GCond
+@mutex: a #GMutex, that is currently locked
 
 
 <!-- ##### FUNCTION g_cond_timed_wait ##### -->
+
 <para>
+Waits until this thread is woken up on @cond, but not longer than
+until the time, that is specified by @abs_time. The @mutex is
+unlocked before falling asleep and locked again before resuming.
+</para>
 
+<para>
+If @abs_time is NULL, g_cond_timed_wait() acts like g_cond_wait().
 </para>
 
-@cond: 
-@mutex: 
-@abs_time: 
-@Returns: 
+<para>
+This function can also be used, if g_thread_init() has not yet been
+called and will immediately return TRUE then.
+</para>
+
+<para>
+To easily calculate @abs_time a combination of g_get_current_time()
+and g_time_val_add() can be used.
+</para>
+
+@cond: a #GCond
+@mutex: a #GMutex, that is currently locked
+@abs_time: a #GTimeVal, determining the final time
+@Returns: TRUE, if the thread is woken up in time
 
 
 <!-- ##### FUNCTION g_cond_free ##### -->
-<para>
 
+<para>
+Destroys the #GCond.
 </para>
 
-@cond: 
+@cond: a #GCond
 
 
 <!-- ##### STRUCT GPrivate ##### -->
 <para>
+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>
 
+<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.
 </para>
+</note>
 
 
 <!-- ##### FUNCTION g_private_new ##### -->
+
 <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>
+<para>
+@destructor is working quite differently from @notify in
+g_static_private_set().
 </para>
+</note>
 
-@destructor: 
-@Returns: 
+<note>
+<para>
+A #GPrivate can not be freed. Reuse it instead, if you can to avoid
+shortage or use #GStaticPrivate.
+</para>
+</note>
+
+<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
+@Returns: a new #GPrivate
 
 
 <!-- ##### FUNCTION g_private_get ##### -->
+
 <para>
+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>
 
+<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.
 </para>
 
-@private_key: 
-@Returns: 
+@private_key: a #GPrivate
+@Returns: the corresponding pointer
 
 
 <!-- ##### FUNCTION g_private_set ##### -->
+
 <para>
+Sets the pointer keyed to @private_key for the current thread.
+</para>
 
+<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.
 </para>
 
-@private_key: 
-@data: 
+@private_key: a #GPrivate
+@data: the new pointer
 
 
 <!-- ##### STRUCT GStaticPrivate ##### -->
+
 <para>
+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>
 
+<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 (&amp;current_number_key);
+
+    if (!current_number)
+    {
+      current_number = g_new (int,1);
+      *current_number = 0;
+      g_static_private_set (&amp;current_number_key, current_number, g_free);
+    }
+    *current_number = calc_next_number (*current_number); 
+    return *current_number;
+  }
+</programlisting>
+</example>
 </para>
 
 @index: 
 
 <!-- ##### MACRO G_STATIC_PRIVATE_INIT ##### -->
 <para>
+Every #GStaticPrivate must be initialized with this macro, before it can
+be used.
+</para>
 
+<para>
+<informalexample>
+<programlisting>
+GStaticPrivate my_private = G_STATIC_PRIVATE_INIT;
+</programlisting>
+</informalexample>
 </para>
 
 
 
-<!-- ##### FUNCTION g_static_private_get ##### -->
+<!-- ##### FUNCTION g_static_private_init ##### -->
 <para>
-
+Initializes @private_key. Alternatively you can initialize it with
+#G_STATIC_PRIVATE_INIT.
 </para>
 
-@private_key: 
-@Returns: 
+@private_key: a #GStaticPrivate to be initialized
 
 
-<!-- ##### FUNCTION g_static_private_get_for_thread ##### -->
+<!-- ##### FUNCTION g_static_private_get ##### -->
 <para>
+Works like g_private_get() only for a #GStaticPrivate.
+</para>
 
+<para>
+This function also works, if g_thread_init() has not yet been called.
 </para>
 
-@private_key: 
-@thread: 
-@Returns: 
+@private_key: a #GStaticPrivate
+@Returns: the corresponding pointer
 
 
 <!-- ##### FUNCTION g_static_private_set ##### -->
 <para>
+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>
 
+<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().
 </para>
 
-@private_key: 
-@data: 
-@notify: 
+<note>
+<para>
+@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
 
 
-<!-- ##### FUNCTION g_static_private_set_for_thread ##### -->
+<!-- ##### FUNCTION g_static_private_free ##### -->
 <para>
+Releases all resources allocated to @private_key. 
+</para>
 
+<para>
+You don't have to call this functions for a #GStaticPrivate with an
+unbounded lifetime, i.e. objects declared 'static', but if you have a
+#GStaticPrivate as a member of a structure and the structure is freed,
+you should also free the #GStaticPrivate.
 </para>
 
-@private_key: 
-@thread: 
-@data: 
-@notify: 
+@private_key: a #GStaticPrivate to be freed