<refentry id="glib-Threads"> <refmeta> <refentrytitle> Threads</refentrytitle> <manvolnum>3</manvolnum> <refmiscinfo>GLIB Library</refmiscinfo> </refmeta> <refnamediv> <refname> Threads</refname><refpurpose> thread abstraction; including threads, different mutexes, conditions and thread private data.</refpurpose> </refnamediv> <refsynopsisdiv><title>Synopsis</title> <synopsis> #include <glib.h> #define <link linkend="G-THREADS-ENABLED-CAPS">G_THREADS_ENABLED</link> #define <link linkend="G-THREADS-IMPL-POSIX-CAPS">G_THREADS_IMPL_POSIX</link> #define <link linkend="G-THREADS-IMPL-SOLARIS-CAPS">G_THREADS_IMPL_SOLARIS</link> #define <link linkend="G-THREADS-IMPL-NONE-CAPS">G_THREADS_IMPL_NONE</link> #define <link linkend="G-THREAD-ERROR-CAPS">G_THREAD_ERROR</link> enum <link linkend="GThreadError">GThreadError</link>; struct <link linkend="GThreadFunctions">GThreadFunctions</link>; <link linkend="void">void</link> <link linkend="g-thread-init">g_thread_init</link> (<link linkend="GThreadFunctions">GThreadFunctions</link> *vtable); <link linkend="gboolean">gboolean</link> <link linkend="g-thread-supported">g_thread_supported</link> (); <link linkend="gpointer">gpointer</link> (<link linkend="GThreadFunc">*GThreadFunc</link>) (<link linkend="gpointer">gpointer</link> data); enum <link linkend="GThreadPriority">GThreadPriority</link>; struct <link linkend="GThread">GThread</link>; <link linkend="GThread">GThread</link>* <link linkend="g-thread-create">g_thread_create</link> (<link linkend="GThreadFunc">GThreadFunc</link> func, <link linkend="gpointer">gpointer</link> data, <link linkend="gboolean">gboolean</link> joinable, <link linkend="GError">GError</link> **error); <link linkend="GThread">GThread</link>* <link linkend="g-thread-create-full">g_thread_create_full</link> (<link linkend="GThreadFunc">GThreadFunc</link> func, <link linkend="gpointer">gpointer</link> data, <link linkend="gulong">gulong</link> stack_size, <link linkend="gboolean">gboolean</link> joinable, <link linkend="gboolean">gboolean</link> bound, <link linkend="GThreadPriority">GThreadPriority</link> priority, <link linkend="GError">GError</link> **error); <link linkend="GThread">GThread</link>* <link linkend="g-thread-self">g_thread_self</link> (void); <link linkend="gpointer">gpointer</link> <link linkend="g-thread-join">g_thread_join</link> (<link linkend="GThread">GThread</link> *thread); <link linkend="void">void</link> <link linkend="g-thread-set-priority">g_thread_set_priority</link> (<link linkend="GThread">GThread</link> *thread, <link linkend="GThreadPriority">GThreadPriority</link> priority); <link linkend="void">void</link> <link linkend="g-thread-yield">g_thread_yield</link> (); <link linkend="void">void</link> <link linkend="g-thread-exit">g_thread_exit</link> (<link linkend="gpointer">gpointer</link> retval); struct <link linkend="GMutex">GMutex</link>; <link linkend="GMutex">GMutex</link>* <link linkend="g-mutex-new">g_mutex_new</link> (); <link linkend="void">void</link> <link linkend="g-mutex-lock">g_mutex_lock</link> (<link linkend="GMutex">GMutex</link> *mutex); <link linkend="gboolean">gboolean</link> <link linkend="g-mutex-trylock">g_mutex_trylock</link> (<link linkend="GMutex">GMutex</link> *mutex); <link linkend="void">void</link> <link linkend="g-mutex-unlock">g_mutex_unlock</link> (<link linkend="GMutex">GMutex</link> *mutex); <link linkend="void">void</link> <link linkend="g-mutex-free">g_mutex_free</link> (<link linkend="GMutex">GMutex</link> *mutex); struct <link linkend="GStaticMutex">GStaticMutex</link>; #define <link linkend="G-STATIC-MUTEX-INIT-CAPS">G_STATIC_MUTEX_INIT</link> <link linkend="void">void</link> <link linkend="g-static-mutex-init">g_static_mutex_init</link> (<link linkend="GStaticMutex">GStaticMutex</link> *mutex); <link linkend="void">void</link> <link linkend="g-static-mutex-lock">g_static_mutex_lock</link> (<link linkend="GStaticMutex">GStaticMutex</link> *mutex); <link linkend="gboolean">gboolean</link> <link linkend="g-static-mutex-trylock">g_static_mutex_trylock</link> (<link linkend="GStaticMutex">GStaticMutex</link> *mutex); <link linkend="void">void</link> <link linkend="g-static-mutex-unlock">g_static_mutex_unlock</link> (<link linkend="GStaticMutex">GStaticMutex</link> *mutex); <link linkend="GMutex">GMutex</link>* <link linkend="g-static-mutex-get-mutex">g_static_mutex_get_mutex</link> (<link linkend="GStaticMutex">GStaticMutex</link> *mutex); <link linkend="void">void</link> <link linkend="g-static-mutex-free">g_static_mutex_free</link> (<link linkend="GStaticMutex">GStaticMutex</link> *mutex); #define <link linkend="G-LOCK-DEFINE-CAPS">G_LOCK_DEFINE</link> (name) #define <link linkend="G-LOCK-DEFINE-STATIC-CAPS">G_LOCK_DEFINE_STATIC</link> (name) #define <link linkend="G-LOCK-EXTERN-CAPS">G_LOCK_EXTERN</link> (name) #define <link linkend="G-LOCK-CAPS">G_LOCK</link> (name) #define <link linkend="G-TRYLOCK-CAPS">G_TRYLOCK</link> (name) #define <link linkend="G-UNLOCK-CAPS">G_UNLOCK</link> (name) struct <link linkend="GStaticRecMutex">GStaticRecMutex</link>; #define <link linkend="G-STATIC-REC-MUTEX-INIT-CAPS">G_STATIC_REC_MUTEX_INIT</link> <link linkend="void">void</link> <link linkend="g-static-rec-mutex-init">g_static_rec_mutex_init</link> (<link linkend="GStaticRecMutex">GStaticRecMutex</link> *mutex); <link linkend="void">void</link> <link linkend="g-static-rec-mutex-lock">g_static_rec_mutex_lock</link> (<link linkend="GStaticRecMutex">GStaticRecMutex</link> *mutex); <link linkend="gboolean">gboolean</link> <link linkend="g-static-rec-mutex-trylock">g_static_rec_mutex_trylock</link> (<link linkend="GStaticRecMutex">GStaticRecMutex</link> *mutex); <link linkend="void">void</link> <link linkend="g-static-rec-mutex-unlock">g_static_rec_mutex_unlock</link> (<link linkend="GStaticRecMutex">GStaticRecMutex</link> *mutex); <link linkend="void">void</link> <link linkend="g-static-rec-mutex-lock-full">g_static_rec_mutex_lock_full</link> (<link linkend="GStaticRecMutex">GStaticRecMutex</link> *mutex, <link linkend="guint">guint</link> depth); <link linkend="guint">guint</link> <link linkend="g-static-rec-mutex-unlock-full">g_static_rec_mutex_unlock_full</link> (<link linkend="GStaticRecMutex">GStaticRecMutex</link> *mutex); <link linkend="void">void</link> <link linkend="g-static-rec-mutex-free">g_static_rec_mutex_free</link> (<link linkend="GStaticRecMutex">GStaticRecMutex</link> *mutex); struct <link linkend="GStaticRWLock">GStaticRWLock</link>; #define <link linkend="G-STATIC-RW-LOCK-INIT-CAPS">G_STATIC_RW_LOCK_INIT</link> <link linkend="void">void</link> <link linkend="g-static-rw-lock-init">g_static_rw_lock_init</link> (<link linkend="GStaticRWLock">GStaticRWLock</link> *lock); <link linkend="void">void</link> <link linkend="g-static-rw-lock-reader-lock">g_static_rw_lock_reader_lock</link> (<link linkend="GStaticRWLock">GStaticRWLock</link> *lock); <link linkend="gboolean">gboolean</link> <link linkend="g-static-rw-lock-reader-trylock">g_static_rw_lock_reader_trylock</link> (<link linkend="GStaticRWLock">GStaticRWLock</link> *lock); <link linkend="void">void</link> <link linkend="g-static-rw-lock-reader-unlock">g_static_rw_lock_reader_unlock</link> (<link linkend="GStaticRWLock">GStaticRWLock</link> *lock); <link linkend="void">void</link> <link linkend="g-static-rw-lock-writer-lock">g_static_rw_lock_writer_lock</link> (<link linkend="GStaticRWLock">GStaticRWLock</link> *lock); <link linkend="gboolean">gboolean</link> <link linkend="g-static-rw-lock-writer-trylock">g_static_rw_lock_writer_trylock</link> (<link linkend="GStaticRWLock">GStaticRWLock</link> *lock); <link linkend="void">void</link> <link linkend="g-static-rw-lock-writer-unlock">g_static_rw_lock_writer_unlock</link> (<link linkend="GStaticRWLock">GStaticRWLock</link> *lock); <link linkend="void">void</link> <link linkend="g-static-rw-lock-free">g_static_rw_lock_free</link> (<link linkend="GStaticRWLock">GStaticRWLock</link> *lock); struct <link linkend="GCond">GCond</link>; <link linkend="GCond">GCond</link>* <link linkend="g-cond-new">g_cond_new</link> (); <link linkend="void">void</link> <link linkend="g-cond-signal">g_cond_signal</link> (<link linkend="GCond">GCond</link> *cond); <link linkend="void">void</link> <link linkend="g-cond-broadcast">g_cond_broadcast</link> (<link linkend="GCond">GCond</link> *cond); <link linkend="void">void</link> <link linkend="g-cond-wait">g_cond_wait</link> (<link linkend="GCond">GCond</link> *cond, <link linkend="GMutex">GMutex</link> *mutex); <link linkend="gboolean">gboolean</link> <link linkend="g-cond-timed-wait">g_cond_timed_wait</link> (<link linkend="GCond">GCond</link> *cond, <link linkend="GMutex">GMutex</link> *mutex, <link linkend="GTimeVal">GTimeVal</link> *abs_time); <link linkend="void">void</link> <link linkend="g-cond-free">g_cond_free</link> (<link linkend="GCond">GCond</link> *cond); struct <link linkend="GPrivate">GPrivate</link>; <link linkend="GPrivate">GPrivate</link>* <link linkend="g-private-new">g_private_new</link> (<link linkend="GDestroyNotify">GDestroyNotify</link> destructor); <link linkend="gpointer">gpointer</link> <link linkend="g-private-get">g_private_get</link> (<link linkend="GPrivate">GPrivate</link> *private_key); <link linkend="void">void</link> <link linkend="g-private-set">g_private_set</link> (<link linkend="GPrivate">GPrivate</link> *private_key, <link linkend="gpointer">gpointer</link> data); struct <link linkend="GStaticPrivate">GStaticPrivate</link>; #define <link linkend="G-STATIC-PRIVATE-INIT-CAPS">G_STATIC_PRIVATE_INIT</link> <link linkend="void">void</link> <link linkend="g-static-private-init">g_static_private_init</link> (<link linkend="GStaticPrivate">GStaticPrivate</link> *private_key); <link linkend="gpointer">gpointer</link> <link linkend="g-static-private-get">g_static_private_get</link> (<link linkend="GStaticPrivate">GStaticPrivate</link> *private_key); <link linkend="void">void</link> <link linkend="g-static-private-set">g_static_private_set</link> (<link linkend="GStaticPrivate">GStaticPrivate</link> *private_key, <link linkend="gpointer">gpointer</link> data, <link linkend="GDestroyNotify">GDestroyNotify</link> notify); <link linkend="void">void</link> <link linkend="g-static-private-free">g_static_private_free</link> (<link linkend="GStaticPrivate">GStaticPrivate</link> *private_key); struct <link linkend="GOnce">GOnce</link>; enum <link linkend="GOnceStatus">GOnceStatus</link>; #define <link linkend="G-ONCE-INIT-CAPS">G_ONCE_INIT</link> #define <link linkend="g-once">g_once</link> (once, func, arg) </synopsis> </refsynopsisdiv> <refsect1> <title>Description</title> <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 (<link linkend="GMutex"><type>GMutex</type></link>, <link linkend="GStaticMutex"><type>GStaticMutex</type></link>, <link linkend="G-LOCK-DEFINE-CAPS"><type>G_LOCK_DEFINE</type></link>, <link linkend="GStaticRecMutex"><type>GStaticRecMutex</type></link> and <link linkend="GStaticRWLock"><type>GStaticRWLock</type></link>), there are primitives for condition variables to allow synchronization of threads (<link linkend="GCond"><type>GCond</type></link>) and finally there are primitives for thread-private data, that every thread has a private instance of (<link linkend="GPrivate"><type>GPrivate</type></link>, <link linkend="GStaticPrivate"><type>GStaticPrivate</type></link>). Last but definitely not least there are primitives to portably create and manage threads (<link linkend="GThread"><type>GThread</type></link>). </para> </refsect1> <refsect1> <title>Details</title> <refsect2> <title><anchor id="G-THREADS-ENABLED-CAPS"/>G_THREADS_ENABLED</title> <indexterm><primary>G_THREADS_ENABLED</primary></indexterm><programlisting>#define G_THREADS_ENABLED </programlisting> <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 <link linkend="g-thread-init"><function>g_thread_init()</function></link>, GLib will be multi-thread safe. It isn't and cannot be, if <link linkend="G-THREADS-ENABLED-CAPS"><type>G_THREADS_ENABLED</type></link> is not defined. </para></refsect2> <refsect2> <title><anchor id="G-THREADS-IMPL-POSIX-CAPS"/>G_THREADS_IMPL_POSIX</title> <indexterm><primary>G_THREADS_IMPL_POSIX</primary></indexterm><programlisting>#define G_THREADS_IMPL_POSIX </programlisting> <para> This macro is defined, if POSIX style threads are used. </para></refsect2> <refsect2> <title><anchor id="G-THREADS-IMPL-SOLARIS-CAPS"/>G_THREADS_IMPL_SOLARIS</title> <indexterm><primary>G_THREADS_IMPL_SOLARIS</primary></indexterm><programlisting>#define G_THREADS_IMPL_SOLARIS </programlisting> <para> This macro is defined, if the Solaris thread system is used. </para></refsect2> <refsect2> <title><anchor id="G-THREADS-IMPL-NONE-CAPS"/>G_THREADS_IMPL_NONE</title> <indexterm><primary>G_THREADS_IMPL_NONE</primary></indexterm><programlisting>#define G_THREADS_IMPL_NONE </programlisting> <para> This macro is defined, if no thread implementation is used. You can however provide one to <link linkend="g-thread-init"><function>g_thread_init()</function></link> to make GLib multi-thread safe. </para></refsect2> <refsect2> <title><anchor id="G-THREAD-ERROR-CAPS"/>G_THREAD_ERROR</title> <indexterm><primary>G_THREAD_ERROR</primary></indexterm><programlisting>#define G_THREAD_ERROR g_thread_error_quark () </programlisting> <para> The error domain of the GLib thread subsystem. </para></refsect2> <refsect2> <title><anchor id="GThreadError"/>enum GThreadError</title> <indexterm><primary>GThreadError</primary></indexterm><programlisting>typedef enum { G_THREAD_ERROR_AGAIN /* Resource temporarily unavailable */ } GThreadError; </programlisting> <para> Possible errors of thread related functions. </para><variablelist role="enum"> <varlistentry> <term><literal>G_THREAD_ERROR_AGAIN</literal></term> <listitem><simpara>a thread couldn't be created due to resource shortage. Try again later. </simpara></listitem> </varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="GThreadFunctions"/>struct GThreadFunctions</title> <indexterm><primary>GThreadFunctions</primary></indexterm><programlisting>struct GThreadFunctions { GMutex* (*mutex_new) (void); void (*mutex_lock) (GMutex *mutex); gboolean (*mutex_trylock) (GMutex *mutex); void (*mutex_unlock) (GMutex *mutex); void (*mutex_free) (GMutex *mutex); GCond* (*cond_new) (void); void (*cond_signal) (GCond *cond); void (*cond_broadcast) (GCond *cond); void (*cond_wait) (GCond *cond, GMutex *mutex); gboolean (*cond_timed_wait) (GCond *cond, GMutex *mutex, GTimeVal *end_time); void (*cond_free) (GCond *cond); GPrivate* (*private_new) (GDestroyNotify destructor); gpointer (*private_get) (GPrivate *private_key); void (*private_set) (GPrivate *private_key, gpointer data); void (*thread_create) (GThreadFunc func, gpointer data, gulong stack_size, gboolean joinable, gboolean bound, GThreadPriority priority, gpointer thread, GError **error); void (*thread_yield) (void); void (*thread_join) (gpointer thread); void (*thread_exit) (void); void (*thread_set_priority)(gpointer thread, GThreadPriority priority); void (*thread_self) (gpointer thread); gboolean (*thread_equal) (gpointer thread1, gpointer thread2); }; </programlisting> <para> This function table is used by <link linkend="g-thread-init"><function>g_thread_init()</function></link> 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 <link linkend="g-mutex-new"><function>g_mutex_new()</function></link> then <link linkend="mutex-new"><function>mutex_new()</function></link> from the table provided to <link linkend="g-thread-init"><function>g_thread_init()</function></link> will be called. </para> <note> <para> This struct should only be used, if you know, what you are doing. </para> </note></refsect2> <refsect2> <title><anchor id="g-thread-init"/>g_thread_init ()</title> <indexterm><primary>g_thread_init</primary></indexterm><programlisting><link linkend="void">void</link> g_thread_init (<link linkend="GThreadFunctions">GThreadFunctions</link> *vtable);</programlisting> <para> Before you use a thread related function in GLib, you should initialize the thread system. This is done by calling <link linkend="g-thread-init"><function>g_thread_init()</function></link>. Most of the time you will only have to call <literal>g_thread_init(NULL)</literal>. </para> <note> <para> You should only call <link linkend="g-thread-init"><function>g_thread_init()</function></link> with a non-<literal>NULL</literal> parameter if you really know what you are doing. </para> </note> <note> <para> <link linkend="g-thread-init"><function>g_thread_init()</function></link> must not be called directly or indirectly as a callback from GLib. Also no mutexes may be currently locked, while calling <link linkend="g-thread-init"><function>g_thread_init()</function></link>. </para> </note> <para> <link linkend="g-thread-init"><function>g_thread_init()</function></link> 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 <link linkend="G-THREADS-ENABLED-CAPS"><type>G_THREADS_ENABLED</type></link> is not defined or <link linkend="G-THREADS-IMPL-NONE-CAPS"><type>G_THREADS_IMPL_NONE</type></link> is defined. </para> <para> If no thread system is available and <parameter>vtable</parameter> is <literal>NULL</literal> or if not all elements of <parameter>vtable</parameter> are non-<literal>NULL</literal>, then <link linkend="g-thread-init"><function>g_thread_init()</function></link> will abort. </para> <note> <para> To use <link linkend="g-thread-init"><function>g_thread_init()</function></link> in your program, you have to link with the libraries that the command <command>pkg-config --libs gthread-2.0</command> 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><variablelist role="params"> <varlistentry><term><parameter>vtable</parameter> :</term> <listitem><simpara>a function table of type <link linkend="GThreadFunctions"><type>GThreadFunctions</type></link>, that provides the entry points to the thread system to be used. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-thread-supported"/>g_thread_supported ()</title> <indexterm><primary>g_thread_supported</primary></indexterm><programlisting><link linkend="gboolean">gboolean</link> g_thread_supported ();</programlisting> <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><variablelist role="params"> <varlistentry><term><emphasis>Returns</emphasis> :</term><listitem><simpara><literal>TRUE</literal>, if the thread system is initialized. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="GThreadFunc"/>GThreadFunc ()</title> <indexterm><primary>GThreadFunc</primary></indexterm><programlisting><link linkend="gpointer">gpointer</link> (*GThreadFunc) (<link linkend="gpointer">gpointer</link> data);</programlisting> <para> Specifies the type of the <parameter>func</parameter> functions passed to <link linkend="g-thread-create"><function>g_thread_create()</function></link> or <link linkend="g-thread-create-full"><function>g_thread_create_full()</function></link>. </para><variablelist role="params"> <varlistentry><term><parameter>data</parameter> :</term> <listitem><simpara>data passed to the thread. </simpara></listitem></varlistentry> <varlistentry><term><emphasis>Returns</emphasis> :</term><listitem><simpara>the return value of the thread, which will be returned by <link linkend="g-thread-join"><function>g_thread_join()</function></link>. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="GThreadPriority"/>enum GThreadPriority</title> <indexterm><primary>GThreadPriority</primary></indexterm><programlisting>typedef enum { G_THREAD_PRIORITY_LOW, G_THREAD_PRIORITY_NORMAL, G_THREAD_PRIORITY_HIGH, G_THREAD_PRIORITY_URGENT } GThreadPriority; </programlisting> <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) there are no thread 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><variablelist role="enum"> <varlistentry> <term><literal>G_THREAD_PRIORITY_LOW</literal></term> <listitem><simpara>a priority lower than normal </simpara></listitem> </varlistentry> <varlistentry> <term><literal>G_THREAD_PRIORITY_NORMAL</literal></term> <listitem><simpara>the default priority </simpara></listitem> </varlistentry> <varlistentry> <term><literal>G_THREAD_PRIORITY_HIGH</literal></term> <listitem><simpara>a priority higher than normal </simpara></listitem> </varlistentry> <varlistentry> <term><literal>G_THREAD_PRIORITY_URGENT</literal></term> <listitem><simpara>the highest priority </simpara></listitem> </varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="GThread"/>struct GThread</title> <indexterm><primary>GThread</primary></indexterm><programlisting>struct GThread { }; </programlisting> <para> The <link linkend="GThread"><type>GThread</type></link> 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 <link linkend="g-thread-join"><function>g_thread_join()</function></link> is called for that thread. </para> </note></refsect2> <refsect2> <title><anchor id="g-thread-create"/>g_thread_create ()</title> <indexterm><primary>g_thread_create</primary></indexterm><programlisting><link linkend="GThread">GThread</link>* g_thread_create (<link linkend="GThreadFunc">GThreadFunc</link> func, <link linkend="gpointer">gpointer</link> data, <link linkend="gboolean">gboolean</link> joinable, <link linkend="GError">GError</link> **error);</programlisting> <para> This function creates a new thread with the default priority. </para> <para> If <parameter>joinable</parameter> is <literal>TRUE</literal>, you can wait for this threads termination calling <link linkend="g-thread-join"><function>g_thread_join()</function></link>. Otherwise the thread will just disappear, when ready. </para> <para> The new thread executes the function <parameter>func</parameter> with the argument <parameter>data</parameter>. If the thread was created successfully, it is returned. </para> <para> <parameter>error</parameter> can be <literal>NULL</literal> to ignore errors, or non-<literal>NULL</literal> to report errors. The error is set, if and only if the function returns <literal>NULL</literal>. </para><variablelist role="params"> <varlistentry><term><parameter>func</parameter> :</term> <listitem><simpara>a function to execute in the new thread. </simpara></listitem></varlistentry> <varlistentry><term><parameter>data</parameter> :</term> <listitem><simpara>an argument to supply to the new thread. </simpara></listitem></varlistentry> <varlistentry><term><parameter>joinable</parameter> :</term> <listitem><simpara>should this thread be joinable? </simpara></listitem></varlistentry> <varlistentry><term><parameter>error</parameter> :</term> <listitem><simpara>return location for error. </simpara></listitem></varlistentry> <varlistentry><term><emphasis>Returns</emphasis> :</term><listitem><simpara>the new <link linkend="GThread"><type>GThread</type></link> on success. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-thread-create-full"/>g_thread_create_full ()</title> <indexterm><primary>g_thread_create_full</primary></indexterm><programlisting><link linkend="GThread">GThread</link>* g_thread_create_full (<link linkend="GThreadFunc">GThreadFunc</link> func, <link linkend="gpointer">gpointer</link> data, <link linkend="gulong">gulong</link> stack_size, <link linkend="gboolean">gboolean</link> joinable, <link linkend="gboolean">gboolean</link> bound, <link linkend="GThreadPriority">GThreadPriority</link> priority, <link linkend="GError">GError</link> **error);</programlisting> <para> This function creates a new thread with the priority <parameter>priority</parameter>. The stack gets the size <parameter>stack_size</parameter> or the default value for the current platform, if <parameter>stack_size</parameter> is 0. </para> <para> If <parameter>joinable</parameter> is <literal>TRUE</literal>, you can wait for this threads termination calling <link linkend="g-thread-join"><function>g_thread_join()</function></link>. Otherwise the thread will just disappear, when ready. If <parameter>bound</parameter> is <literal>TRUE</literal>, 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> <para> The new thread executes the function <parameter>func</parameter> with the argument <parameter>data</parameter>. If the thread was created successfully, it is returned. </para> <para> <parameter>error</parameter> can be <literal>NULL</literal> to ignore errors, or non-<literal>NULL</literal> to report errors. The error is set, if and only if the function returns <literal>NULL</literal>. </para> <note> <para> It is not guaranteed, that threads with different priorities really behave accordingly. On some systems (e.g. Linux) there are no thread 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 <literal>G_THREAD_PRIORITY_NORMAL</literal> here as a default. </para> </note> <note> <para> Only use <link linkend="g-thread-create-full"><function>g_thread_create_full()</function></link>, when you really can't use <link linkend="g-thread-create"><function>g_thread_create()</function></link> instead. <link linkend="g-thread-create"><function>g_thread_create()</function></link> does not take <parameter>stack_size</parameter>, <parameter>bound</parameter> and <parameter>priority</parameter> as arguments, as they should only be used for cases, where it is inevitable. </para> </note><variablelist role="params"> <varlistentry><term><parameter>func</parameter> :</term> <listitem><simpara>a function to execute in the new thread. </simpara></listitem></varlistentry> <varlistentry><term><parameter>data</parameter> :</term> <listitem><simpara>an argument to supply to the new thread. </simpara></listitem></varlistentry> <varlistentry><term><parameter>stack_size</parameter> :</term> <listitem><simpara>a stack size for the new thread. </simpara></listitem></varlistentry> <varlistentry><term><parameter>joinable</parameter> :</term> <listitem><simpara>should this thread be joinable? </simpara></listitem></varlistentry> <varlistentry><term><parameter>bound</parameter> :</term> <listitem><simpara>should this thread be bound to a system thread? </simpara></listitem></varlistentry> <varlistentry><term><parameter>priority</parameter> :</term> <listitem><simpara>a priority for the thread. </simpara></listitem></varlistentry> <varlistentry><term><parameter>error</parameter> :</term> <listitem><simpara>return location for error. </simpara></listitem></varlistentry> <varlistentry><term><emphasis>Returns</emphasis> :</term><listitem><simpara>the new <link linkend="GThread"><type>GThread</type></link> on success. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-thread-self"/>g_thread_self ()</title> <indexterm><primary>g_thread_self</primary></indexterm><programlisting><link linkend="GThread">GThread</link>* g_thread_self (void);</programlisting> <para> This functions returns the <link linkend="GThread"><type>GThread</type></link> corresponding to the calling thread. </para><variablelist role="params"> <varlistentry><term><emphasis>Returns</emphasis> :</term><listitem><simpara>the current thread. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-thread-join"/>g_thread_join ()</title> <indexterm><primary>g_thread_join</primary></indexterm><programlisting><link linkend="gpointer">gpointer</link> g_thread_join (<link linkend="GThread">GThread</link> *thread);</programlisting> <para> Waits until <parameter>thread</parameter> finishes, i.e. the function <parameter>func</parameter>, as given to <link linkend="g-thread-create"><function>g_thread_create()</function></link>, returns or <link linkend="g-thread-exit"><function>g_thread_exit()</function></link> is called by <parameter>thread</parameter>. All resources of <parameter>thread</parameter> including the <link linkend="GThread"><type>GThread</type></link> struct are released. <parameter>thread</parameter> must have been created with <parameter>joinable</parameter>=<literal>TRUE</literal> in <link linkend="g-thread-create"><function>g_thread_create()</function></link>. The value returned by <parameter>func</parameter> or given to <link linkend="g-thread-exit"><function>g_thread_exit()</function></link> by <parameter>thread</parameter> is returned by this function. </para><variablelist role="params"> <varlistentry><term><parameter>thread</parameter> :</term> <listitem><simpara>a <link linkend="GThread"><type>GThread</type></link> to be waited for. </simpara></listitem></varlistentry> <varlistentry><term><emphasis>Returns</emphasis> :</term><listitem><simpara>the return value of the thread. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-thread-set-priority"/>g_thread_set_priority ()</title> <indexterm><primary>g_thread_set_priority</primary></indexterm><programlisting><link linkend="void">void</link> g_thread_set_priority (<link linkend="GThread">GThread</link> *thread, <link linkend="GThreadPriority">GThreadPriority</link> priority);</programlisting> <para> Changes the priority of <parameter>thread</parameter> to <parameter>priority</parameter>. </para> <note> <para> It is not guaranteed, that threads with different priorities really behave accordingly. On some systems (e.g. Linux) there are no thread 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><variablelist role="params"> <varlistentry><term><parameter>thread</parameter> :</term> <listitem><simpara>a <link linkend="GThread"><type>GThread</type></link>. </simpara></listitem></varlistentry> <varlistentry><term><parameter>priority</parameter> :</term> <listitem><simpara>a new priority for <parameter>thread</parameter>. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-thread-yield"/>g_thread_yield ()</title> <indexterm><primary>g_thread_yield</primary></indexterm><programlisting><link linkend="void">void</link> g_thread_yield ();</programlisting> <para> Gives 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></refsect2> <refsect2> <title><anchor id="g-thread-exit"/>g_thread_exit ()</title> <indexterm><primary>g_thread_exit</primary></indexterm><programlisting><link linkend="void">void</link> g_thread_exit (<link linkend="gpointer">gpointer</link> retval);</programlisting> <para> Exits the current thread. If another thread is waiting for that thread using <link linkend="g-thread-join"><function>g_thread_join()</function></link> and the current thread is joinable, the waiting thread will be woken up and getting <parameter>retval</parameter> as the return value of <link linkend="g-thread-join"><function>g_thread_join()</function></link>. If the current thread is not joinable, <parameter>retval</parameter> is ignored. Calling </para> <para> <informalexample> <programlisting> g_thread_exit (retval); </programlisting> </informalexample> </para> <para> is equivalent to calling </para> <para> <informalexample> <programlisting> return retval; </programlisting> </informalexample> </para> <para> in the function <parameter>func</parameter>, as given to <link linkend="g-thread-create"><function>g_thread_create()</function></link>. </para> <note> <para> Never call <link linkend="g-thread-exit"><function>g_thread_exit()</function></link> from within a thread of a <link linkend="GThreadPool"><type>GThreadPool</type></link>, as that will mess up the bookkeeping and lead to funny and unwanted results. </para> </note><variablelist role="params"> <varlistentry><term><parameter>retval</parameter> :</term> <listitem><simpara>the return value of this thread. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="GMutex"/>struct GMutex</title> <indexterm><primary>GMutex</primary></indexterm><programlisting>struct GMutex;</programlisting> <para> The <link linkend="GMutex"><type>GMutex</type></link> 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> <link linkend="GStaticMutex"><type>GStaticMutex</type></link> 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 <link linkend="g-thread-init"><function>g_thread_init()</function></link> first, you can not use a <link linkend="GMutex"><type>GMutex</type></link>, as <link linkend="g-mutex-new"><function>g_mutex_new()</function></link> requires that. Use a <link linkend="GStaticMutex"><type>GStaticMutex</type></link> instead. </para> <para> A <link linkend="GMutex"><type>GMutex</type></link> should only be accessed via the following functions. </para> <note> <para> All of the <function>g_mutex_*</function> functions are actually macros. Apart from taking their addresses, you can however use them as if they were functions. </para> </note></refsect2> <refsect2> <title><anchor id="g-mutex-new"/>g_mutex_new ()</title> <indexterm><primary>g_mutex_new</primary></indexterm><programlisting><link linkend="GMutex">GMutex</link>* g_mutex_new ();</programlisting> <para> Creates a new <link linkend="GMutex"><type>GMutex</type></link>. </para> <note> <para> This function will abort, if <link linkend="g-thread-init"><function>g_thread_init()</function></link> has not been called yet. </para> </note><variablelist role="params"> <varlistentry><term><emphasis>Returns</emphasis> :</term><listitem><simpara>a new <link linkend="GMutex"><type>GMutex</type></link>. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-mutex-lock"/>g_mutex_lock ()</title> <indexterm><primary>g_mutex_lock</primary></indexterm><programlisting><link linkend="void">void</link> g_mutex_lock (<link linkend="GMutex">GMutex</link> *mutex);</programlisting> <para> Locks <parameter>mutex</parameter>. If <parameter>mutex</parameter> is already locked by another thread, the current thread will block until <parameter>mutex</parameter> is unlocked by the other thread. </para> <para> This function can also be used, if <link linkend="g-thread-init"><function>g_thread_init()</function></link> has not yet been called and will do nothing then. </para> <note> <para> <link linkend="GMutex"><type>GMutex</type></link> is neither guaranteed to be recursive nor to be non-recursive, i.e. a thread could deadlock while calling <link linkend="g-mutex-lock"><function>g_mutex_lock()</function></link>, if it already has locked <parameter>mutex</parameter>. Use <link linkend="GStaticRecMutex"><type>GStaticRecMutex</type></link>, if you need recursive mutexes. </para> </note><variablelist role="params"> <varlistentry><term><parameter>mutex</parameter> :</term> <listitem><simpara>a <link linkend="GMutex"><type>GMutex</type></link>. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-mutex-trylock"/>g_mutex_trylock ()</title> <indexterm><primary>g_mutex_trylock</primary></indexterm><programlisting><link linkend="gboolean">gboolean</link> g_mutex_trylock (<link linkend="GMutex">GMutex</link> *mutex);</programlisting> <para> Tries to lock <parameter>mutex</parameter>. If <parameter>mutex</parameter> is already locked by another thread, it immediately returns <literal>FALSE</literal>. Otherwise it locks <parameter>mutex</parameter> and returns <literal>TRUE</literal>. </para> <para> This function can also be used, if <link linkend="g-thread-init"><function>g_thread_init()</function></link> has not yet been called and will immediately return <literal>TRUE</literal> then. </para> <note> <para> <link linkend="GMutex"><type>GMutex</type></link> is neither guaranteed to be recursive nor to be non-recursive, i.e. the return value of <link linkend="g-mutex-trylock"><function>g_mutex_trylock()</function></link> could be both <literal>FALSE</literal> or <literal>TRUE</literal>, if the current thread already has locked <parameter>mutex</parameter>. Use <link linkend="GStaticRecMutex"><type>GStaticRecMutex</type></link>, if you need recursive mutexes. </para> </note><variablelist role="params"> <varlistentry><term><parameter>mutex</parameter> :</term> <listitem><simpara>a <link linkend="GMutex"><type>GMutex</type></link>. </simpara></listitem></varlistentry> <varlistentry><term><emphasis>Returns</emphasis> :</term><listitem><simpara><literal>TRUE</literal>, if <parameter>mutex</parameter> could be locked. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-mutex-unlock"/>g_mutex_unlock ()</title> <indexterm><primary>g_mutex_unlock</primary></indexterm><programlisting><link linkend="void">void</link> g_mutex_unlock (<link linkend="GMutex">GMutex</link> *mutex);</programlisting> <para> Unlocks <parameter>mutex</parameter>. If another thread is blocked in a <link linkend="g-mutex-lock"><function>g_mutex_lock()</function></link> call for <parameter>mutex</parameter>, it will be woken and can lock <parameter>mutex</parameter> itself. </para> <para> This function can also be used, if <link linkend="g-thread-init"><function>g_thread_init()</function></link> has not yet been called and will do nothing then. </para><variablelist role="params"> <varlistentry><term><parameter>mutex</parameter> :</term> <listitem><simpara>a <link linkend="GMutex"><type>GMutex</type></link>. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-mutex-free"/>g_mutex_free ()</title> <indexterm><primary>g_mutex_free</primary></indexterm><programlisting><link linkend="void">void</link> g_mutex_free (<link linkend="GMutex">GMutex</link> *mutex);</programlisting> <para> Destroys <parameter>mutex</parameter>. </para><variablelist role="params"> <varlistentry><term><parameter>mutex</parameter> :</term> <listitem><simpara>a <link linkend="GMutex"><type>GMutex</type></link>. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="GStaticMutex"/>struct GStaticMutex</title> <indexterm><primary>GStaticMutex</primary></indexterm><programlisting>struct GStaticMutex;</programlisting> <para> A <link linkend="GStaticMutex"><type>GStaticMutex</type></link> works like a <link linkend="GMutex"><type>GMutex</type></link>, but it has one significant advantage. It doesn't need to be created at run-time like a <link linkend="GMutex"><type>GMutex</type></link>, but can be defined at compile-time. Here is a shorter, easier and safer version of our <function><link linkend="give-me-next-number"><function>give_me_next_number()</function></link></function> example: </para> <para> <example> <title>Using <structname>GStaticMutex</structname> 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> <para> Sometimes you would like to dynamically create a mutex. If you don't want to require prior calling to <link linkend="g-thread-init"><function>g_thread_init()</function></link>, because your code should also be usable in non-threaded programs, you are not able to use <link linkend="g-mutex-new"><function>g_mutex_new()</function></link> and thus <link linkend="GMutex"><type>GMutex</type></link>, as that requires a prior call to <link linkend="g-thread-init"><function>g_thread_init()</function></link>. In theses cases you can also use a <link linkend="GStaticMutex"><type>GStaticMutex</type></link>. It must be initialized with <link linkend="g-static-mutex-init"><function>g_static_mutex_init()</function></link> before using it and freed with with <link linkend="g-static-mutex-free"><function>g_static_mutex_free()</function></link> when not needed anymore to free up any allocated resources. </para> <para> Even though <link linkend="GStaticMutex"><type>GStaticMutex</type></link> 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 <function>g_static_mutex_*</function> functions can also be used, if <link linkend="g-thread-init"><function>g_thread_init()</function></link> has not yet been called. </para> <note> <para> All of the <function>g_static_mutex_*</function> functions are actually macros. Apart from taking their addresses, you can however use them as if they were functions. </para> </note></refsect2> <refsect2> <title><anchor id="G-STATIC-MUTEX-INIT-CAPS"/>G_STATIC_MUTEX_INIT</title> <indexterm><primary>G_STATIC_MUTEX_INIT</primary></indexterm><programlisting>#define G_STATIC_MUTEX_INIT </programlisting> <para> A <link linkend="GStaticMutex"><type>GStaticMutex</type></link> 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 <link linkend="g-static-mutex-init"><function>g_static_mutex_init()</function></link>. </para> <para> <informalexample> <programlisting> GStaticMutex my_mutex = G_STATIC_MUTEX_INIT; </programlisting> </informalexample> </para></refsect2> <refsect2> <title><anchor id="g-static-mutex-init"/>g_static_mutex_init ()</title> <indexterm><primary>g_static_mutex_init</primary></indexterm><programlisting><link linkend="void">void</link> g_static_mutex_init (<link linkend="GStaticMutex">GStaticMutex</link> *mutex);</programlisting> <para> Initializes <parameter>mutex</parameter>. Alternatively you can initialize it with <link linkend="G-STATIC-MUTEX-INIT-CAPS"><type>G_STATIC_MUTEX_INIT</type></link>. </para><variablelist role="params"> <varlistentry><term><parameter>mutex</parameter> :</term> <listitem><simpara>a <link linkend="GStaticMutex"><type>GStaticMutex</type></link> to be initialized. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-static-mutex-lock"/>g_static_mutex_lock ()</title> <indexterm><primary>g_static_mutex_lock</primary></indexterm><programlisting><link linkend="void">void</link> g_static_mutex_lock (<link linkend="GStaticMutex">GStaticMutex</link> *mutex);</programlisting> <para> Works like <link linkend="g-mutex-lock"><function>g_mutex_lock()</function></link>, but for a <link linkend="GStaticMutex"><type>GStaticMutex</type></link>. </para><variablelist role="params"> <varlistentry><term><parameter>mutex</parameter> :</term> <listitem><simpara>a <link linkend="GStaticMutex"><type>GStaticMutex</type></link>. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-static-mutex-trylock"/>g_static_mutex_trylock ()</title> <indexterm><primary>g_static_mutex_trylock</primary></indexterm><programlisting><link linkend="gboolean">gboolean</link> g_static_mutex_trylock (<link linkend="GStaticMutex">GStaticMutex</link> *mutex);</programlisting> <para> Works like <link linkend="g-mutex-trylock"><function>g_mutex_trylock()</function></link>, but for a <link linkend="GStaticMutex"><type>GStaticMutex</type></link>. </para><variablelist role="params"> <varlistentry><term><parameter>mutex</parameter> :</term> <listitem><simpara>a <link linkend="GStaticMutex"><type>GStaticMutex</type></link>. </simpara></listitem></varlistentry> <varlistentry><term><emphasis>Returns</emphasis> :</term><listitem><simpara><literal>TRUE</literal>, if the <link linkend="GStaticMutex"><type>GStaticMutex</type></link> could be locked. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-static-mutex-unlock"/>g_static_mutex_unlock ()</title> <indexterm><primary>g_static_mutex_unlock</primary></indexterm><programlisting><link linkend="void">void</link> g_static_mutex_unlock (<link linkend="GStaticMutex">GStaticMutex</link> *mutex);</programlisting> <para> Works like <link linkend="g-mutex-unlock"><function>g_mutex_unlock()</function></link>, but for a <link linkend="GStaticMutex"><type>GStaticMutex</type></link>. </para><variablelist role="params"> <varlistentry><term><parameter>mutex</parameter> :</term> <listitem><simpara>a <link linkend="GStaticMutex"><type>GStaticMutex</type></link>. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-static-mutex-get-mutex"/>g_static_mutex_get_mutex ()</title> <indexterm><primary>g_static_mutex_get_mutex</primary></indexterm><programlisting><link linkend="GMutex">GMutex</link>* g_static_mutex_get_mutex (<link linkend="GStaticMutex">GStaticMutex</link> *mutex);</programlisting> <para> For some operations (like <link linkend="g-cond-wait"><function>g_cond_wait()</function></link>) you must have a <link linkend="GMutex"><type>GMutex</type></link> instead of a <link linkend="GStaticMutex"><type>GStaticMutex</type></link>. This function will return the corresponding <link linkend="GMutex"><type>GMutex</type></link> for <parameter>mutex</parameter>. </para><variablelist role="params"> <varlistentry><term><parameter>mutex</parameter> :</term> <listitem><simpara>a <link linkend="GStaticMutex"><type>GStaticMutex</type></link>. </simpara></listitem></varlistentry> <varlistentry><term><emphasis>Returns</emphasis> :</term><listitem><simpara>the <link linkend="GMutex"><type>GMutex</type></link> corresponding to <parameter>mutex</parameter>. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-static-mutex-free"/>g_static_mutex_free ()</title> <indexterm><primary>g_static_mutex_free</primary></indexterm><programlisting><link linkend="void">void</link> g_static_mutex_free (<link linkend="GStaticMutex">GStaticMutex</link> *mutex);</programlisting> <para> Releases all resources allocated to <parameter>mutex</parameter>. </para> <para> You don't have to call this functions for a <link linkend="GStaticMutex"><type>GStaticMutex</type></link> with an unbounded lifetime, i.e. objects declared 'static', but if you have a <link linkend="GStaticMutex"><type>GStaticMutex</type></link> as a member of a structure and the structure is freed, you should also free the <link linkend="GStaticMutex"><type>GStaticMutex</type></link>. </para><variablelist role="params"> <varlistentry><term><parameter>mutex</parameter> :</term> <listitem><simpara>a <link linkend="GStaticMutex"><type>GStaticMutex</type></link> to be freed. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="G-LOCK-DEFINE-CAPS"/>G_LOCK_DEFINE()</title> <indexterm><primary>G_LOCK_DEFINE</primary></indexterm><programlisting>#define G_LOCK_DEFINE(name)</programlisting> <para> The <literal>G_LOCK_</literal>* macros provide a convenient interface to <link linkend="GStaticMutex"><type>GStaticMutex</type></link> with the advantage that they will expand to nothing in programs compiled against a thread-disabled GLib, saving code and memory there. <link linkend="G-LOCK-DEFINE-CAPS"><type>G_LOCK_DEFINE</type></link> 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 <parameter>name</parameter> parameter will be mangled to get the name of the <link linkend="GStaticMutex"><type>GStaticMutex</type></link>. 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 <function><link linkend="give-me-next-number"><function>give_me_next_number()</function></link></function> example using the <literal>G_LOCK_</literal>* macros: </para> <para> <example> <title>Using the <literal>G_LOCK_</literal>* 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><variablelist role="params"> <varlistentry><term><parameter>name</parameter> :</term> <listitem><simpara>the name of the lock. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="G-LOCK-DEFINE-STATIC-CAPS"/>G_LOCK_DEFINE_STATIC()</title> <indexterm><primary>G_LOCK_DEFINE_STATIC</primary></indexterm><programlisting>#define G_LOCK_DEFINE_STATIC(name)</programlisting> <para> This works like <link linkend="G-LOCK-DEFINE-CAPS"><type>G_LOCK_DEFINE</type></link>, but it creates a static object. </para><variablelist role="params"> <varlistentry><term><parameter>name</parameter> :</term> <listitem><simpara>the name of the lock. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="G-LOCK-EXTERN-CAPS"/>G_LOCK_EXTERN()</title> <indexterm><primary>G_LOCK_EXTERN</primary></indexterm><programlisting>#define G_LOCK_EXTERN(name)</programlisting> <para> This declares a lock, that is defined with <link linkend="G-LOCK-DEFINE-CAPS"><type>G_LOCK_DEFINE</type></link> in another module. </para><variablelist role="params"> <varlistentry><term><parameter>name</parameter> :</term> <listitem><simpara>the name of the lock. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="G-LOCK-CAPS"/>G_LOCK()</title> <indexterm><primary>G_LOCK</primary></indexterm><programlisting>#define G_LOCK(name)</programlisting> <para> Works like <link linkend="g-mutex-lock"><function>g_mutex_lock()</function></link>, but for a lock defined with <link linkend="G-LOCK-DEFINE-CAPS"><type>G_LOCK_DEFINE</type></link>. </para><variablelist role="params"> <varlistentry><term><parameter>name</parameter> :</term> <listitem><simpara>the name of the lock. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="G-TRYLOCK-CAPS"/>G_TRYLOCK()</title> <indexterm><primary>G_TRYLOCK</primary></indexterm><programlisting>#define G_TRYLOCK(name)</programlisting> <para> Works like <link linkend="g-mutex-trylock"><function>g_mutex_trylock()</function></link>, but for a lock defined with <link linkend="G-LOCK-DEFINE-CAPS"><type>G_LOCK_DEFINE</type></link>. </para><variablelist role="params"> <varlistentry><term><parameter>name</parameter> :</term> <listitem><simpara>the name of the lock. </simpara></listitem></varlistentry> <varlistentry><term><emphasis>Returns</emphasis> :</term><listitem><simpara><literal>TRUE</literal>, if the lock could be locked. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="G-UNLOCK-CAPS"/>G_UNLOCK()</title> <indexterm><primary>G_UNLOCK</primary></indexterm><programlisting>#define G_UNLOCK(name)</programlisting> <para> Works like <link linkend="g-mutex-unlock"><function>g_mutex_unlock()</function></link>, but for a lock defined with <link linkend="G-LOCK-DEFINE-CAPS"><type>G_LOCK_DEFINE</type></link>. </para><variablelist role="params"> <varlistentry><term><parameter>name</parameter> :</term> <listitem><simpara>the name of the lock. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="GStaticRecMutex"/>struct GStaticRecMutex</title> <indexterm><primary>GStaticRecMutex</primary></indexterm><programlisting>struct GStaticRecMutex { }; </programlisting> <para> A <link linkend="GStaticRecMutex"><type>GStaticRecMutex</type></link> works like a <link linkend="GStaticMutex"><type>GStaticMutex</type></link>, 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 <link linkend="g-static-rec-mutex-unlock-full"><function>g_static_rec_mutex_unlock_full()</function></link>, that allows you to unlock a <link linkend="GStaticRecMutex"><type>GStaticRecMutex</type></link> 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 <link linkend="g-static-rec-mutex-lock-full"><function>g_static_rec_mutex_lock_full()</function></link>. </para> <para> Even though <link linkend="GStaticRecMutex"><type>GStaticRecMutex</type></link> is not opaque, it should only be used with the following functions. </para> <para> All of the <function>g_static_rec_mutex_*</function> functions can also be used, if <link linkend="g-thread-init"><function>g_thread_init()</function></link> has not been called. </para></refsect2> <refsect2> <title><anchor id="G-STATIC-REC-MUTEX-INIT-CAPS"/>G_STATIC_REC_MUTEX_INIT</title> <indexterm><primary>G_STATIC_REC_MUTEX_INIT</primary></indexterm><programlisting>#define G_STATIC_REC_MUTEX_INIT { G_STATIC_MUTEX_INIT } </programlisting> <para> A <link linkend="GStaticRecMutex"><type>GStaticRecMutex</type></link> 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 <link linkend="g-static-rec-mutex-init"><function>g_static_rec_mutex_init()</function></link>. </para> <para> <informalexample> <programlisting> GStaticRecMutex my_mutex = G_STATIC_REC_MUTEX_INIT; </programlisting> </informalexample> </para></refsect2> <refsect2> <title><anchor id="g-static-rec-mutex-init"/>g_static_rec_mutex_init ()</title> <indexterm><primary>g_static_rec_mutex_init</primary></indexterm><programlisting><link linkend="void">void</link> g_static_rec_mutex_init (<link linkend="GStaticRecMutex">GStaticRecMutex</link> *mutex);</programlisting> <para> A <link linkend="GStaticRecMutex"><type>GStaticRecMutex</type></link> must be initialized with this function, before it can be used. Alternatively you can initialize it with <link linkend="G-STATIC-REC-MUTEX-INIT-CAPS"><type>G_STATIC_REC_MUTEX_INIT</type></link>. </para><variablelist role="params"> <varlistentry><term><parameter>mutex</parameter> :</term> <listitem><simpara>a <link linkend="GStaticRecMutex"><type>GStaticRecMutex</type></link> to be initialized. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-static-rec-mutex-lock"/>g_static_rec_mutex_lock ()</title> <indexterm><primary>g_static_rec_mutex_lock</primary></indexterm><programlisting><link linkend="void">void</link> g_static_rec_mutex_lock (<link linkend="GStaticRecMutex">GStaticRecMutex</link> *mutex);</programlisting> <para> Locks <parameter>mutex</parameter>. If <parameter>mutex</parameter> is already locked by another thread, the current thread will block until <parameter>mutex</parameter> is unlocked by the other thread. If <parameter>mutex</parameter> is already locked by the calling thread, this functions increases the depth of <parameter>mutex</parameter> and returns immediately. </para><variablelist role="params"> <varlistentry><term><parameter>mutex</parameter> :</term> <listitem><simpara>a <link linkend="GStaticRecMutex"><type>GStaticRecMutex</type></link> to lock. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-static-rec-mutex-trylock"/>g_static_rec_mutex_trylock ()</title> <indexterm><primary>g_static_rec_mutex_trylock</primary></indexterm><programlisting><link linkend="gboolean">gboolean</link> g_static_rec_mutex_trylock (<link linkend="GStaticRecMutex">GStaticRecMutex</link> *mutex);</programlisting> <para> Tries to lock <parameter>mutex</parameter>. If <parameter>mutex</parameter> is already locked by another thread, it immediately returns <literal>FALSE</literal>. Otherwise it locks <parameter>mutex</parameter> and returns <literal>TRUE</literal>. If <parameter>mutex</parameter> is already locked by the calling thread, this functions increases the depth of <parameter>mutex</parameter> and immediately returns <literal>TRUE</literal>. </para><variablelist role="params"> <varlistentry><term><parameter>mutex</parameter> :</term> <listitem><simpara>a <link linkend="GStaticRecMutex"><type>GStaticRecMutex</type></link> to lock. </simpara></listitem></varlistentry> <varlistentry><term><emphasis>Returns</emphasis> :</term><listitem><simpara><literal>TRUE</literal>, if <parameter>mutex</parameter> could be locked. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-static-rec-mutex-unlock"/>g_static_rec_mutex_unlock ()</title> <indexterm><primary>g_static_rec_mutex_unlock</primary></indexterm><programlisting><link linkend="void">void</link> g_static_rec_mutex_unlock (<link linkend="GStaticRecMutex">GStaticRecMutex</link> *mutex);</programlisting> <para> Unlocks <parameter>mutex</parameter>. Another threads can, however, only lock <parameter>mutex</parameter> when it has been unlocked as many times, as it had been locked before. If <parameter>mutex</parameter> is completely unlocked and another thread is blocked in a <link linkend="g-static-rec-mutex-lock"><function>g_static_rec_mutex_lock()</function></link> call for <parameter>mutex</parameter>, it will be woken and can lock <parameter>mutex</parameter> itself. </para><variablelist role="params"> <varlistentry><term><parameter>mutex</parameter> :</term> <listitem><simpara>a <link linkend="GStaticRecMutex"><type>GStaticRecMutex</type></link> to unlock. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-static-rec-mutex-lock-full"/>g_static_rec_mutex_lock_full ()</title> <indexterm><primary>g_static_rec_mutex_lock_full</primary></indexterm><programlisting><link linkend="void">void</link> g_static_rec_mutex_lock_full (<link linkend="GStaticRecMutex">GStaticRecMutex</link> *mutex, <link linkend="guint">guint</link> depth);</programlisting> <para> Works like calling <link linkend="g-static-rec-mutex-lock"><function>g_static_rec_mutex_lock()</function></link> for <parameter>mutex</parameter> <parameter>depth</parameter> times. </para><variablelist role="params"> <varlistentry><term><parameter>mutex</parameter> :</term> <listitem><simpara>a <link linkend="GStaticRecMutex"><type>GStaticRecMutex</type></link> to lock. </simpara></listitem></varlistentry> <varlistentry><term><parameter>depth</parameter> :</term> <listitem><simpara>number of times this mutex has to be unlocked to be completely unlocked. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-static-rec-mutex-unlock-full"/>g_static_rec_mutex_unlock_full ()</title> <indexterm><primary>g_static_rec_mutex_unlock_full</primary></indexterm><programlisting><link linkend="guint">guint</link> g_static_rec_mutex_unlock_full (<link linkend="GStaticRecMutex">GStaticRecMutex</link> *mutex);</programlisting> <para> Completely unlocks <parameter>mutex</parameter>. If another thread is blocked in a <link linkend="g-static-rec-mutex-lock"><function>g_static_rec_mutex_lock()</function></link> call for <parameter>mutex</parameter>, it will be woken and can lock <parameter>mutex</parameter> itself. This function returns the number of times, that <parameter>mutex</parameter> has been locked by the current thread. To restore the state before the call to <link linkend="g-static-rec-mutex-unlock-full"><function>g_static_rec_mutex_unlock_full()</function></link> you can call <link linkend="g-static-rec-mutex-lock-full"><function>g_static_rec_mutex_lock_full()</function></link> with the depth returned by this function. </para><variablelist role="params"> <varlistentry><term><parameter>mutex</parameter> :</term> <listitem><simpara>a <link linkend="GStaticRecMutex"><type>GStaticRecMutex</type></link> to completely unlock. </simpara></listitem></varlistentry> <varlistentry><term><emphasis>Returns</emphasis> :</term><listitem><simpara>number of times <parameter>mutex</parameter> has been locked by the current thread. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-static-rec-mutex-free"/>g_static_rec_mutex_free ()</title> <indexterm><primary>g_static_rec_mutex_free</primary></indexterm><programlisting><link linkend="void">void</link> g_static_rec_mutex_free (<link linkend="GStaticRecMutex">GStaticRecMutex</link> *mutex);</programlisting> <para> Releases all resources allocated to a <link linkend="GStaticRecMutex"><type>GStaticRecMutex</type></link>. </para> <para> You don't have to call this functions for a <link linkend="GStaticRecMutex"><type>GStaticRecMutex</type></link> with an unbounded lifetime, i.e. objects declared 'static', but if you have a <link linkend="GStaticRecMutex"><type>GStaticRecMutex</type></link> as a member of a structure and the structure is freed, you should also free the <link linkend="GStaticRecMutex"><type>GStaticRecMutex</type></link>. </para><variablelist role="params"> <varlistentry><term><parameter>mutex</parameter> :</term> <listitem><simpara>a <link linkend="GStaticRecMutex"><type>GStaticRecMutex</type></link> to be freed. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="GStaticRWLock"/>struct GStaticRWLock</title> <indexterm><primary>GStaticRWLock</primary></indexterm><programlisting>struct GStaticRWLock { }; </programlisting> <para> The <link linkend="GStaticRWLock"><type>GStaticRWLock</type></link> 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 (&rwlock); if (index < array->len) retval = g_ptr_array_index (array, index); g_static_rw_lock_reader_unlock (&rwlock); return retval; } void my_array_set (guint index, gpointer data) { g_static_rw_lock_writer_lock (&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 (&rwlock); } </programlisting> </example> </para> <para> This example shows an array, which can be accessed by many readers (the <function><link linkend="my-array-get"><function>my_array_get()</function></link></function> function) simultaneously, whereas the writers (the <function><link linkend="my-array-set"><function>my_array_set()</function></link></function> function) will only 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 these 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 <link linkend="GStaticRWLock"><type>GStaticRWLock</type></link> is not opaque, it should only be used with the following functions. </para> <para> All of the <function>g_static_rw_lock_*</function> functions can also be used, if <link linkend="g-thread-init"><function>g_thread_init()</function></link> has not been called. </para> <note> <para> A read-write lock has a higher overhead as a mutex. For example both <link linkend="g-static-rw-lock-reader-lock"><function>g_static_rw_lock_reader_lock()</function></link> and <link linkend="g-static-rw-lock-reader-unlock"><function>g_static_rw_lock_reader_unlock()</function></link> have to lock and unlock a <link linkend="GStaticMutex"><type>GStaticMutex</type></link>, so it takes at least twice the time to lock and unlock a <link linkend="GStaticRWLock"><type>GStaticRWLock</type></link> than to lock and unlock a <link linkend="GStaticMutex"><type>GStaticMutex</type></link>. So only data structures, that are accessed by multiple readers, which keep the lock for a considerable time justify a <link linkend="GStaticRWLock"><type>GStaticRWLock</type></link>. The above example most probably would fare better with a <link linkend="GStaticMutex"><type>GStaticMutex</type></link>. </para> </note></refsect2> <refsect2> <title><anchor id="G-STATIC-RW-LOCK-INIT-CAPS"/>G_STATIC_RW_LOCK_INIT</title> <indexterm><primary>G_STATIC_RW_LOCK_INIT</primary></indexterm><programlisting>#define G_STATIC_RW_LOCK_INIT { G_STATIC_MUTEX_INIT, NULL, NULL, 0, FALSE, 0, 0 } </programlisting> <para> A <link linkend="GStaticRWLock"><type>GStaticRWLock</type></link> 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 <link linkend="g-static-rw-lock-init"><function>g_static_rw_lock_init()</function></link>. </para> <para> <informalexample> <programlisting> GStaticRWLock my_lock = G_STATIC_RW_LOCK_INIT; </programlisting> </informalexample> </para></refsect2> <refsect2> <title><anchor id="g-static-rw-lock-init"/>g_static_rw_lock_init ()</title> <indexterm><primary>g_static_rw_lock_init</primary></indexterm><programlisting><link linkend="void">void</link> g_static_rw_lock_init (<link linkend="GStaticRWLock">GStaticRWLock</link> *lock);</programlisting> <para> A <link linkend="GStaticRWLock"><type>GStaticRWLock</type></link> must be initialized with this function, before it can be used. Alternatively you can initialize it with <link linkend="G-STATIC-RW-LOCK-INIT-CAPS"><type>G_STATIC_RW_LOCK_INIT</type></link>. </para><variablelist role="params"> <varlistentry><term><parameter>lock</parameter> :</term> <listitem><simpara>a <link linkend="GStaticRWLock"><type>GStaticRWLock</type></link> to be initialized. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-static-rw-lock-reader-lock"/>g_static_rw_lock_reader_lock ()</title> <indexterm><primary>g_static_rw_lock_reader_lock</primary></indexterm><programlisting><link linkend="void">void</link> g_static_rw_lock_reader_lock (<link linkend="GStaticRWLock">GStaticRWLock</link> *lock);</programlisting> <para> Locks <parameter>lock</parameter> for reading. There may be unlimited concurrent locks for reading of a <link linkend="GStaticRWLock"><type>GStaticRWLock</type></link> at the same time. If <parameter>lock</parameter> is already locked for writing by another thread or if another thread is already waiting to lock <parameter>lock</parameter> for writing, this function will block until <parameter>lock</parameter> is unlocked by the other writing thread and no other writing threads want to lock <parameter>lock</parameter>. This lock has to be unlocked by <link linkend="g-static-rw-lock-reader-unlock"><function>g_static_rw_lock_reader_unlock()</function></link>. </para> <para> <link linkend="GStaticRWLock"><type>GStaticRWLock</type></link> is not recursive. It might seem to be possible to recursively lock for reading, but that can result in a deadlock as well, due to writer preference. </para><variablelist role="params"> <varlistentry><term><parameter>lock</parameter> :</term> <listitem><simpara>a <link linkend="GStaticRWLock"><type>GStaticRWLock</type></link> to lock for reading. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-static-rw-lock-reader-trylock"/>g_static_rw_lock_reader_trylock ()</title> <indexterm><primary>g_static_rw_lock_reader_trylock</primary></indexterm><programlisting><link linkend="gboolean">gboolean</link> g_static_rw_lock_reader_trylock (<link linkend="GStaticRWLock">GStaticRWLock</link> *lock);</programlisting> <para> Tries to lock <parameter>lock</parameter> for reading. If <parameter>lock</parameter> is already locked for writing by another thread or if another thread is already waiting to lock <parameter>lock</parameter> for writing, it immediately returns <literal>FALSE</literal>. Otherwise it locks <parameter>lock</parameter> for reading and returns <literal>TRUE</literal>. This lock has to be unlocked by <link linkend="g-static-rw-lock-reader-unlock"><function>g_static_rw_lock_reader_unlock()</function></link>. </para><variablelist role="params"> <varlistentry><term><parameter>lock</parameter> :</term> <listitem><simpara>a <link linkend="GStaticRWLock"><type>GStaticRWLock</type></link> to lock for reading. </simpara></listitem></varlistentry> <varlistentry><term><emphasis>Returns</emphasis> :</term><listitem><simpara><literal>TRUE</literal>, if <parameter>lock</parameter> could be locked for reading. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-static-rw-lock-reader-unlock"/>g_static_rw_lock_reader_unlock ()</title> <indexterm><primary>g_static_rw_lock_reader_unlock</primary></indexterm><programlisting><link linkend="void">void</link> g_static_rw_lock_reader_unlock (<link linkend="GStaticRWLock">GStaticRWLock</link> *lock);</programlisting> <para> Unlocks <parameter>lock</parameter>. If a thread waits to lock <parameter>lock</parameter> for writing and all locks for reading have been unlocked, the waiting thread is woken up and can lock <parameter>lock</parameter> for writing. </para><variablelist role="params"> <varlistentry><term><parameter>lock</parameter> :</term> <listitem><simpara>a <link linkend="GStaticRWLock"><type>GStaticRWLock</type></link> to unlock after reading. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-static-rw-lock-writer-lock"/>g_static_rw_lock_writer_lock ()</title> <indexterm><primary>g_static_rw_lock_writer_lock</primary></indexterm><programlisting><link linkend="void">void</link> g_static_rw_lock_writer_lock (<link linkend="GStaticRWLock">GStaticRWLock</link> *lock);</programlisting> <para> Locks <parameter>lock</parameter> for writing. If <parameter>lock</parameter> is already locked for writing or reading by other threads, this function will block until <parameter>lock</parameter> is completely unlocked and then lock <parameter>lock</parameter> for writing. While this functions waits to lock <parameter>lock</parameter>, no other thread can lock <parameter>lock</parameter> for reading. When <parameter>lock</parameter> is locked for writing, no other thread can lock <parameter>lock</parameter> (neither for reading nor writing). This lock has to be unlocked by <link linkend="g-static-rw-lock-writer-unlock"><function>g_static_rw_lock_writer_unlock()</function></link>. </para><variablelist role="params"> <varlistentry><term><parameter>lock</parameter> :</term> <listitem><simpara>a <link linkend="GStaticRWLock"><type>GStaticRWLock</type></link> to lock for writing. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-static-rw-lock-writer-trylock"/>g_static_rw_lock_writer_trylock ()</title> <indexterm><primary>g_static_rw_lock_writer_trylock</primary></indexterm><programlisting><link linkend="gboolean">gboolean</link> g_static_rw_lock_writer_trylock (<link linkend="GStaticRWLock">GStaticRWLock</link> *lock);</programlisting> <para> Tries to lock <parameter>lock</parameter> for writing. If <parameter>lock</parameter> is already locked (for either reading or writing) by another thread, it immediately returns <literal>FALSE</literal>. Otherwise it locks <parameter>lock</parameter> for writing and returns <literal>TRUE</literal>. This lock has to be unlocked by <link linkend="g-static-rw-lock-writer-unlock"><function>g_static_rw_lock_writer_unlock()</function></link>. </para><variablelist role="params"> <varlistentry><term><parameter>lock</parameter> :</term> <listitem><simpara>a <link linkend="GStaticRWLock"><type>GStaticRWLock</type></link> to lock for writing. </simpara></listitem></varlistentry> <varlistentry><term><emphasis>Returns</emphasis> :</term><listitem><simpara><literal>TRUE</literal>, if <parameter>lock</parameter> could be locked for writing. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-static-rw-lock-writer-unlock"/>g_static_rw_lock_writer_unlock ()</title> <indexterm><primary>g_static_rw_lock_writer_unlock</primary></indexterm><programlisting><link linkend="void">void</link> g_static_rw_lock_writer_unlock (<link linkend="GStaticRWLock">GStaticRWLock</link> *lock);</programlisting> <para> Unlocks <parameter>lock</parameter>. If a thread waits to lock <parameter>lock</parameter> for writing and all locks for reading have been unlocked, the waiting thread is woken up and can lock <parameter>lock</parameter> for writing. If no thread waits to lock <parameter>lock</parameter> for writing and threads wait to lock <parameter>lock</parameter> for reading, the waiting threads are woken up and can lock <parameter>lock</parameter> for reading. </para><variablelist role="params"> <varlistentry><term><parameter>lock</parameter> :</term> <listitem><simpara>a <link linkend="GStaticRWLock"><type>GStaticRWLock</type></link> to unlock after writing. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-static-rw-lock-free"/>g_static_rw_lock_free ()</title> <indexterm><primary>g_static_rw_lock_free</primary></indexterm><programlisting><link linkend="void">void</link> g_static_rw_lock_free (<link linkend="GStaticRWLock">GStaticRWLock</link> *lock);</programlisting> <para> Releases all resources allocated to <parameter>lock</parameter>. </para> <para> You don't have to call this functions for a <link linkend="GStaticRWLock"><type>GStaticRWLock</type></link> with an unbounded lifetime, i.e. objects declared 'static', but if you have a <link linkend="GStaticRWLock"><type>GStaticRWLock</type></link> as a member of a structure and the structure is freed, you should also free the <link linkend="GStaticRWLock"><type>GStaticRWLock</type></link>. </para><variablelist role="params"> <varlistentry><term><parameter>lock</parameter> :</term> <listitem><simpara>a <link linkend="GStaticRWLock"><type>GStaticRWLock</type></link> to be freed. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="GCond"/>struct GCond</title> <indexterm><primary>GCond</primary></indexterm><programlisting>struct GCond;</programlisting> <para> The <link linkend="GCond"><type>GCond</type></link> struct is an opaque data structure to represent a condition. A <link linkend="GCond"><type>GCond</type></link> 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 <link linkend="GCond"><type>GCond</type></link>, 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 <function><link linkend="pop-data"><function>pop_data()</function></link></function> now, it will wait until current_data is non-<literal>NULL</literal>, i.e. until some other thread has called <function><link linkend="push-data"><function>push_data()</function></link></function>. </para> <note> <para> It is important to use the <link linkend="g-cond-wait"><function>g_cond_wait()</function></link> and <link linkend="g-cond-timed-wait"><function>g_cond_timed_wait()</function></link> 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 <link linkend="GMutex"><type>GMutex</type></link>, like above. </para> </note> <para> A <link linkend="GCond"><type>GCond</type></link> should only be accessed via the following functions. </para> <note> <para> All of the <function>g_cond_*</function> functions are actually macros. Apart from taking their addresses, you can however use them as if they were functions. </para> </note></refsect2> <refsect2> <title><anchor id="g-cond-new"/>g_cond_new ()</title> <indexterm><primary>g_cond_new</primary></indexterm><programlisting><link linkend="GCond">GCond</link>* g_cond_new ();</programlisting> <para> Creates a new <link linkend="GCond"><type>GCond</type></link>. This function will abort, if <link linkend="g-thread-init"><function>g_thread_init()</function></link> has not been called yet. </para><variablelist role="params"> <varlistentry><term><emphasis>Returns</emphasis> :</term><listitem><simpara>a new <link linkend="GCond"><type>GCond</type></link>. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-cond-signal"/>g_cond_signal ()</title> <indexterm><primary>g_cond_signal</primary></indexterm><programlisting><link linkend="void">void</link> g_cond_signal (<link linkend="GCond">GCond</link> *cond);</programlisting> <para> If threads are waiting for <parameter>cond</parameter>, 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 <link linkend="g-thread-init"><function>g_thread_init()</function></link> has not yet been called and will do nothing then. </para><variablelist role="params"> <varlistentry><term><parameter>cond</parameter> :</term> <listitem><simpara>a <link linkend="GCond"><type>GCond</type></link>. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-cond-broadcast"/>g_cond_broadcast ()</title> <indexterm><primary>g_cond_broadcast</primary></indexterm><programlisting><link linkend="void">void</link> g_cond_broadcast (<link linkend="GCond">GCond</link> *cond);</programlisting> <para> If threads are waiting for <parameter>cond</parameter>, 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 <link linkend="g-thread-init"><function>g_thread_init()</function></link> has not yet been called and will do nothing then. </para><variablelist role="params"> <varlistentry><term><parameter>cond</parameter> :</term> <listitem><simpara>a <link linkend="GCond"><type>GCond</type></link>. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-cond-wait"/>g_cond_wait ()</title> <indexterm><primary>g_cond_wait</primary></indexterm><programlisting><link linkend="void">void</link> g_cond_wait (<link linkend="GCond">GCond</link> *cond, <link linkend="GMutex">GMutex</link> *mutex);</programlisting> <para> Waits until this thread is woken up on <parameter>cond</parameter>. The <parameter>mutex</parameter> is unlocked before falling asleep and locked again before resuming. </para> <para> This function can also be used, if <link linkend="g-thread-init"><function>g_thread_init()</function></link> has not yet been called and will immediately return then. </para><variablelist role="params"> <varlistentry><term><parameter>cond</parameter> :</term> <listitem><simpara>a <link linkend="GCond"><type>GCond</type></link>. </simpara></listitem></varlistentry> <varlistentry><term><parameter>mutex</parameter> :</term> <listitem><simpara>a <link linkend="GMutex"><type>GMutex</type></link>, that is currently locked. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-cond-timed-wait"/>g_cond_timed_wait ()</title> <indexterm><primary>g_cond_timed_wait</primary></indexterm><programlisting><link linkend="gboolean">gboolean</link> g_cond_timed_wait (<link linkend="GCond">GCond</link> *cond, <link linkend="GMutex">GMutex</link> *mutex, <link linkend="GTimeVal">GTimeVal</link> *abs_time);</programlisting> <para> Waits until this thread is woken up on <parameter>cond</parameter>, but not longer than until the time, that is specified by <parameter>abs_time</parameter>. The <parameter>mutex</parameter> is unlocked before falling asleep and locked again before resuming. </para> <para> If <parameter>abs_time</parameter> is <literal>NULL</literal>, <link linkend="g-cond-timed-wait"><function>g_cond_timed_wait()</function></link> acts like <link linkend="g-cond-wait"><function>g_cond_wait()</function></link>. </para> <para> This function can also be used, if <link linkend="g-thread-init"><function>g_thread_init()</function></link> has not yet been called and will immediately return <literal>TRUE</literal> then. </para> <para> To easily calculate <parameter>abs_time</parameter> a combination of <link linkend="g-get-current-time"><function>g_get_current_time()</function></link> and <link linkend="g-time-val-add"><function>g_time_val_add()</function></link> can be used. </para><variablelist role="params"> <varlistentry><term><parameter>cond</parameter> :</term> <listitem><simpara>a <link linkend="GCond"><type>GCond</type></link>. </simpara></listitem></varlistentry> <varlistentry><term><parameter>mutex</parameter> :</term> <listitem><simpara>a <link linkend="GMutex"><type>GMutex</type></link>, that is currently locked. </simpara></listitem></varlistentry> <varlistentry><term><parameter>abs_time</parameter> :</term> <listitem><simpara>a <link linkend="GTimeVal"><type>GTimeVal</type></link>, determining the final time. </simpara></listitem></varlistentry> <varlistentry><term><emphasis>Returns</emphasis> :</term><listitem><simpara><literal>TRUE</literal>, if the thread is woken up in time. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-cond-free"/>g_cond_free ()</title> <indexterm><primary>g_cond_free</primary></indexterm><programlisting><link linkend="void">void</link> g_cond_free (<link linkend="GCond">GCond</link> *cond);</programlisting> <para> Destroys the <link linkend="GCond"><type>GCond</type></link>. </para><variablelist role="params"> <varlistentry><term><parameter>cond</parameter> :</term> <listitem><simpara>a <link linkend="GCond"><type>GCond</type></link>. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="GPrivate"/>struct GPrivate</title> <indexterm><primary>GPrivate</primary></indexterm><programlisting>struct GPrivate;</programlisting> <para> The <link linkend="GPrivate"><type>GPrivate</type></link> 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 <function><link linkend="give-me-next-number"><function>give_me_next_number()</function></link></function> example from above. Now we don't want <literal>current_number</literal> 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 <literal>current_number_key</literal> is read. If it is <literal>NULL</literal>, 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 <link linkend="GPrivate"><type>GPrivate</type></link> struct should only be accessed via the following functions. </para> <note> <para> All of the <function>g_private_*</function> functions are actually macros. Apart from taking their addresses, you can however use them as if they were functions. </para> </note></refsect2> <refsect2> <title><anchor id="g-private-new"/>g_private_new ()</title> <indexterm><primary>g_private_new</primary></indexterm><programlisting><link linkend="GPrivate">GPrivate</link>* g_private_new (<link linkend="GDestroyNotify">GDestroyNotify</link> destructor);</programlisting> <para> Creates a new <link linkend="GPrivate"><type>GPrivate</type></link>. If <parameter>destructor</parameter> is non-<literal>NULL</literal>, it is a pointer to a destructor function. Whenever a thread ends and the corresponding pointer keyed to this instance of <link linkend="GPrivate"><type>GPrivate</type></link> is non-<literal>NULL</literal>, the destructor is called with this pointer as the argument. </para> <note> <para> <parameter>destructor</parameter> is working quite differently from <parameter>notify</parameter> in <link linkend="g-static-private-set"><function>g_static_private_set()</function></link>. </para> </note> <note> <para> A <link linkend="GPrivate"><type>GPrivate</type></link> can not be freed. Reuse it instead, if you can to avoid shortage or use <link linkend="GStaticPrivate"><type>GStaticPrivate</type></link>. </para> </note> <note> <para> This function will abort, if <link linkend="g-thread-init"><function>g_thread_init()</function></link> has not been called yet. </para> </note><variablelist role="params"> <varlistentry><term><parameter>destructor</parameter> :</term> <listitem><simpara>a function to handle the data keyed to <link linkend="GPrivate"><type>GPrivate</type></link>, when a thread ends. </simpara></listitem></varlistentry> <varlistentry><term><emphasis>Returns</emphasis> :</term><listitem><simpara>a new <link linkend="GPrivate"><type>GPrivate</type></link>. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-private-get"/>g_private_get ()</title> <indexterm><primary>g_private_get</primary></indexterm><programlisting><link linkend="gpointer">gpointer</link> g_private_get (<link linkend="GPrivate">GPrivate</link> *private_key);</programlisting> <para> Returns the pointer keyed to <parameter>private_key</parameter> for the current thread. This pointer is <literal>NULL</literal>, when <link linkend="g-private-set"><function>g_private_set()</function></link> hasn't been called for the current <parameter>private_key</parameter> and thread yet. </para> <para> This function can also be used, if <link linkend="g-thread-init"><function>g_thread_init()</function></link> has not yet been called and will return the value of <parameter>private_key</parameter> casted to <link linkend="gpointer"><type>gpointer</type></link> then. </para><variablelist role="params"> <varlistentry><term><parameter>private_key</parameter> :</term> <listitem><simpara>a <link linkend="GPrivate"><type>GPrivate</type></link>. </simpara></listitem></varlistentry> <varlistentry><term><emphasis>Returns</emphasis> :</term><listitem><simpara>the corresponding pointer. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-private-set"/>g_private_set ()</title> <indexterm><primary>g_private_set</primary></indexterm><programlisting><link linkend="void">void</link> g_private_set (<link linkend="GPrivate">GPrivate</link> *private_key, <link linkend="gpointer">gpointer</link> data);</programlisting> <para> Sets the pointer keyed to <parameter>private_key</parameter> for the current thread. </para> <para> This function can also be used, if <link linkend="g-thread-init"><function>g_thread_init()</function></link> has not yet been called and will set <parameter>private_key</parameter> to <parameter>data</parameter> casted to <link linkend="GPrivate"><type>GPrivate</type></link>* then. </para><variablelist role="params"> <varlistentry><term><parameter>private_key</parameter> :</term> <listitem><simpara>a <link linkend="GPrivate"><type>GPrivate</type></link>. </simpara></listitem></varlistentry> <varlistentry><term><parameter>data</parameter> :</term> <listitem><simpara>the new pointer. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="GStaticPrivate"/>struct GStaticPrivate</title> <indexterm><primary>GStaticPrivate</primary></indexterm><programlisting>struct GStaticPrivate { }; </programlisting> <para> A <link linkend="GStaticPrivate"><type>GStaticPrivate</type></link> works almost like a <link linkend="GPrivate"><type>GPrivate</type></link>, but it has one significant advantage. It doesn't need to be created at run-time like a <link linkend="GPrivate"><type>GPrivate</type></link>, but can be defined at compile-time. This is similar to the difference between <link linkend="GMutex"><type>GMutex</type></link> and <link linkend="GStaticMutex"><type>GStaticMutex</type></link>. Now look at our <function><link linkend="give-me-next-number"><function>give_me_next_number()</function></link></function> example with <link linkend="GStaticPrivate"><type>GStaticPrivate</type></link>: </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 (&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> </para></refsect2> <refsect2> <title><anchor id="G-STATIC-PRIVATE-INIT-CAPS"/>G_STATIC_PRIVATE_INIT</title> <indexterm><primary>G_STATIC_PRIVATE_INIT</primary></indexterm><programlisting>#define G_STATIC_PRIVATE_INIT </programlisting> <para> Every <link linkend="GStaticPrivate"><type>GStaticPrivate</type></link> 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></refsect2> <refsect2> <title><anchor id="g-static-private-init"/>g_static_private_init ()</title> <indexterm><primary>g_static_private_init</primary></indexterm><programlisting><link linkend="void">void</link> g_static_private_init (<link linkend="GStaticPrivate">GStaticPrivate</link> *private_key);</programlisting> <para> Initializes <parameter>private_key</parameter>. Alternatively you can initialize it with <link linkend="G-STATIC-PRIVATE-INIT-CAPS"><type>G_STATIC_PRIVATE_INIT</type></link>. </para><variablelist role="params"> <varlistentry><term><parameter>private_key</parameter> :</term> <listitem><simpara>a <link linkend="GStaticPrivate"><type>GStaticPrivate</type></link> to be initialized. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-static-private-get"/>g_static_private_get ()</title> <indexterm><primary>g_static_private_get</primary></indexterm><programlisting><link linkend="gpointer">gpointer</link> g_static_private_get (<link linkend="GStaticPrivate">GStaticPrivate</link> *private_key);</programlisting> <para> Works like <link linkend="g-private-get"><function>g_private_get()</function></link> only for a <link linkend="GStaticPrivate"><type>GStaticPrivate</type></link>. </para> <para> This function also works, if <link linkend="g-thread-init"><function>g_thread_init()</function></link> has not yet been called. </para><variablelist role="params"> <varlistentry><term><parameter>private_key</parameter> :</term> <listitem><simpara>a <link linkend="GStaticPrivate"><type>GStaticPrivate</type></link>. </simpara></listitem></varlistentry> <varlistentry><term><emphasis>Returns</emphasis> :</term><listitem><simpara>the corresponding pointer. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-static-private-set"/>g_static_private_set ()</title> <indexterm><primary>g_static_private_set</primary></indexterm><programlisting><link linkend="void">void</link> g_static_private_set (<link linkend="GStaticPrivate">GStaticPrivate</link> *private_key, <link linkend="gpointer">gpointer</link> data, <link linkend="GDestroyNotify">GDestroyNotify</link> notify);</programlisting> <para> Sets the pointer keyed to <parameter>private_key</parameter> for the current thread and the function <parameter>notify</parameter> to be called with that pointer (<literal>NULL</literal> or non-<literal>NULL</literal>), whenever the pointer is set again or whenever the current thread ends. </para> <para> This function also works, if <link linkend="g-thread-init"><function>g_thread_init()</function></link> has not yet been called. If <link linkend="g-thread-init"><function>g_thread_init()</function></link> is called later, the <parameter>data</parameter> keyed to <parameter>private_key</parameter> will be inherited only by the main thread, i.e. the one that called <link linkend="g-thread-init"><function>g_thread_init()</function></link>. </para> <note> <para> <parameter>notify</parameter> is working quite differently from <parameter>destructor</parameter> in <link linkend="g-private-new"><function>g_private_new()</function></link>. </para> </note><variablelist role="params"> <varlistentry><term><parameter>private_key</parameter> :</term> <listitem><simpara>a <link linkend="GStaticPrivate"><type>GStaticPrivate</type></link>. </simpara></listitem></varlistentry> <varlistentry><term><parameter>data</parameter> :</term> <listitem><simpara>the new pointer. </simpara></listitem></varlistentry> <varlistentry><term><parameter>notify</parameter> :</term> <listitem><simpara>a function to be called with the pointer, whenever the current thread ends or sets this pointer again. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="g-static-private-free"/>g_static_private_free ()</title> <indexterm><primary>g_static_private_free</primary></indexterm><programlisting><link linkend="void">void</link> g_static_private_free (<link linkend="GStaticPrivate">GStaticPrivate</link> *private_key);</programlisting> <para> Releases all resources allocated to <parameter>private_key</parameter>. </para> <para> You don't have to call this functions for a <link linkend="GStaticPrivate"><type>GStaticPrivate</type></link> with an unbounded lifetime, i.e. objects declared 'static', but if you have a <link linkend="GStaticPrivate"><type>GStaticPrivate</type></link> as a member of a structure and the structure is freed, you should also free the <link linkend="GStaticPrivate"><type>GStaticPrivate</type></link>. </para><variablelist role="params"> <varlistentry><term><parameter>private_key</parameter> :</term> <listitem><simpara>a <link linkend="GStaticPrivate"><type>GStaticPrivate</type></link> to be freed. </simpara></listitem></varlistentry> </variablelist></refsect2> <refsect2> <title><anchor id="GOnce"/>struct GOnce</title> <indexterm role="2.4"><primary>GOnce</primary></indexterm><programlisting>struct GOnce { volatile GOnceStatus status; volatile gpointer retval; }; </programlisting> <para> A <structname>GOnce</structname> struct controls a one-time initialization function. Any one-time initialization function must have its own unique <structname>GOnce</structname> struct. </para><para>Since 2.4 </para></refsect2> <refsect2> <title><anchor id="GOnceStatus"/>enum GOnceStatus</title> <indexterm role="2.4"><primary>GOnceStatus</primary></indexterm><programlisting>typedef enum { G_ONCE_STATUS_NOTCALLED, G_ONCE_STATUS_PROGRESS, G_ONCE_STATUS_READY } GOnceStatus; </programlisting> <para> The possible stati of a one-time initialization function controlled by a <link linkend="GOnce"><type>GOnce</type></link> struct. </para><variablelist role="enum"> <varlistentry> <term><literal>G_ONCE_STATUS_NOTCALLED</literal></term> <listitem><simpara>the function has not been called yet. </simpara></listitem> </varlistentry> <varlistentry> <term><literal>G_ONCE_STATUS_PROGRESS</literal></term> <listitem><simpara>the function call is currently in progress. </simpara></listitem> </varlistentry> <varlistentry> <term><literal>G_ONCE_STATUS_READY</literal></term> <listitem><simpara>the function has been called. </simpara></listitem> </varlistentry> </variablelist><para>Since 2.4 </para></refsect2> <refsect2> <title><anchor id="G-ONCE-INIT-CAPS"/>G_ONCE_INIT</title> <indexterm role="2.4"><primary>G_ONCE_INIT</primary></indexterm><programlisting>#define G_ONCE_INIT { G_ONCE_STATUS_NOTCALLED, NULL } </programlisting> <para> A <link linkend="GOnce"><type>GOnce</type></link> must be initialized with this macro, before it can be used. </para> <para> <informalexample> <programlisting> GOnce my_once = G_ONCE_INIT; </programlisting> </informalexample> </para><para>Since 2.4 </para></refsect2> <refsect2> <title><anchor id="g-once"/>g_once()</title> <indexterm role="2.4"><primary>g_once</primary></indexterm><programlisting>#define g_once(once, func, arg)</programlisting> <para> The first call to this routine by a process with a given <link linkend="GOnce"><type>GOnce</type></link> struct calls <parameter>func</parameter> with the given argument. Thereafter, subsequent calls to <link linkend="g-once"><function>g_once()</function></link> with the same <link linkend="GOnce"><type>GOnce</type></link> struct do not call <parameter>func</parameter> again, but return the stored result of the first call. On return from <link linkend="g-once"><function>g_once()</function></link>, the status of <parameter>once</parameter> will be <literal>G_ONCE_STATUS_READY</literal>. </para> <para> For example, a mutex or a thread-specific data key must be created exactly once. In a threaded environment, calling <link linkend="g-once"><function>g_once()</function></link> ensures that the initialization is serialized across multiple threads. </para> <note><para> Calling <link linkend="g-once"><function>g_once()</function></link> recursively on the same <link linkend="GOnce"><type>GOnce</type></link> struct in <parameter>func</parameter> will lead to a deadlock. </para></note> <para> <informalexample> <programlisting> gpointer <link linkend="get-debug-flags"><function>get_debug_flags()</function></link> { static GOnce my_once = G_ONCE_INIT; g_once (&my_once, parse_debug_flags, NULL); return my_once.retval; } </programlisting> </informalexample> </para><variablelist role="params"> <varlistentry><term><parameter>once</parameter> :</term> <listitem><simpara>a <link linkend="GOnce"><type>GOnce</type></link> structure </simpara></listitem></varlistentry> <varlistentry><term><parameter>func</parameter> :</term> <listitem><simpara>the function associated to <parameter>once</parameter>. This function is called only once, regardless of the number of times it and its associated <link linkend="GOnce"><type>GOnce</type></link> struct are passed to <link linkend="g-once"><function>g_once()</function></link> . </simpara></listitem></varlistentry> <varlistentry><term><parameter>arg</parameter> :</term> <listitem><simpara> data to be passed to <parameter>func</parameter> </simpara></listitem></varlistentry> </variablelist><para>Since 2.4 </para></refsect2> </refsect1> <refsect1> <title>See Also</title> <para> <variablelist> <varlistentry> <term><link linkend="GThreadPool"><type>GThreadPool</type></link></term> <listitem><para>Thread pools.</para></listitem> </varlistentry> <varlistentry> <term><link linkend="GAsyncQueue"><type>GAsyncQueue</type></link></term> <listitem><para>Send asynchronous messages between threads.</para></listitem> </varlistentry> </variablelist> </para> </refsect1> </refentry>