<para>
The aim of the thread related functions in GLib is to provide a
-portable means for writing multithreaded software. There are
+portable means for writing multi-threaded software. There are
primitives for mutexes to protect the access to portions of memory
(#GMutex, #GStaticMutex, #G_LOCK_DEFINE, #GStaticRecMutex and
#GStaticRWLock), there are primitives for condition variables to allow
This macro is defined, if GLib was compiled with thread support. This
does not necessarily mean, that there is a thread implementation
available, but the infrastructure is in place and once you provide a
-thread implementation to g_thread_init(), GLib will be multithread
+thread implementation to g_thread_init(), GLib will be multi-thread
safe. It isn't and cannot be, if #G_THREADS_ENABLED is not defined.
</para>
<para>
This macro is defined, if no thread implementation is used. You can
-however provide one to g_thread_init() to make GLib multithread safe.
+however provide one to g_thread_init() to make GLib multi-thread safe.
</para>
<note>
<para>
g_thread_init() must not be called directly or indirectly as a
-callback from GLib. Also no mutexes may be currently locked, while
+call-back from GLib. Also no mutexes may be currently locked, while
calling g_thread_init().
</para>
</note>
<!-- ##### USER_FUNCTION GThreadFunc ##### -->
<para>
-Specifies the type of the @thread_func functions passed to
-g_thread_create().
+Specifies the type of the @func functions passed to
+g_thread_create() or g_thread_create_full().
</para>
-@value: data supplied to the thread
+@data: data passed to the thread
+@Returns: the return value of the thread, which will be returned by
+g_thread_join()
<!-- ##### ENUM GThreadPriority ##### -->
<!-- ##### STRUCT GThread ##### -->
<para>
-The #Gthread struct represents a running thread. It has three public
-members, but the underlying struct is bigger, so you must not copy
-this struct. You also must not write that information.
+The #GThread struct represents a running thread. It has three public
+read-only members, but the underlying struct is bigger, so you must
+not copy this struct.
</para>
<note>
</para>
</note>
+@func: the function executing in that thread
+@data: the argument to the function
@joinable: is this thread joinable?
-@bound: is this thread bound to a system thread?
@priority: the priority of the thread
<!-- ##### FUNCTION g_thread_create ##### -->
<para>
+This function creates a new thread with the priority @priority.
+</para>
+
+<para>
+If @joinable is #TRUE, you can wait for this threads termination
+calling g_thread_wait(). Otherwise the thread will just disappear, when
+ready.
+</para>
+
+<para>
+The new thread executes the function @func with the argument
+@data. If the thread was created successfully, it is returned.
+</para>
+
+<para>
+@error can be NULL to ignore errors, or non-NULL to report errors. The
+error is set, if and only if the function returns #NULL.
+</para>
+
+@func: a function to execute in the new thread
+@data: an argument to supply to the new thread
+@joinable: should this thread be joinable?
+@error: return location for error.
+@Returns: the new #GThread on success
+
+
+<!-- ##### FUNCTION g_thread_create_full ##### -->
+<para>
This function creates a new thread with the priority @priority. The
stack gets the size @stack_size or the default value for the current
platform, if @stack_size is 0.
</para>
<para>
-The new thread executes the function @thread_func with the argument
-@arg. If the thread was created successfully, it is returned.
+The new thread executes the function @func with the argument
+@data. If the thread was created successfully, it is returned.
</para>
<para>
</para>
</note>
-@thread_func: a function to execute in the new thread
-@arg: an argument to supply to the new thread
+<note>
+<para>
+Only use g_thread_create_full(), when you really can't use
+g_thread_create() instead. g_thread_create() does not take
+@stack_size, @bound and @priority as arguments, as they should only be
+used for cases, where it is inevitable.
+</para>
+</note>
+
+@func: a function to execute in the new thread
+@data: an argument to supply to the new thread
@stack_size: a stack size for the new thread
@joinable: should this thread be joinable?
@bound: should this thread be bound to a system thread?
<!-- ##### FUNCTION g_thread_join ##### -->
<para>
-Waits until @thread finishes, i.e. the function @thread_func, as given
+Waits until @thread finishes, i.e. the function @func, as given
to g_thread_create, returns or g_thread_exit() is called by
@thread. All resources of @thread including the #GThread struct are
released. @thread must have been created with @joinable=#TRUE in
-g_thread_create().
+g_thread_create(). The value returned by @func or given to
+g_thread_exit() by @thread is returned by this function.
</para>
@thread: a #GThread to be waited for
+@Returns: the return value of the thread
<!-- ##### FUNCTION g_thread_set_priority ##### -->
<!-- ##### FUNCTION g_thread_exit ##### -->
<para>
Exit the current thread. If another thread is waiting for that thread
-using g_thread_join(), that thread will be woken up.
+using g_thread_join() and the current thread is joinable, the waiting
+thread will be woken up and getting @retval as the return value of
+g_thread_join(). If the current thread is not joinable, @retval is
+ignored. Calling
+</para>
+
+<para>
+<informalexample>
+<programlisting>
+g_thread_join (retval);
+</programlisting>
+</informalexample>
+</para>
+
+<para>
+is equivalent to calling
+</para>
+
+<para>
+<informalexample>
+<programlisting>
+return retval;
+</programlisting>
+</informalexample>
+</para>
+
+<para>
+in the function @func, as given to g_thread_create().
</para>
<note>
</para>
</note>
+@retval: the return value of this thread
<!-- ##### STRUCT GMutex ##### -->
</para>
<para>
-It is easy to see, that this won't work in a multithreaded
+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>
<note>
<para>
#GMutex is not recursive, i.e. a thread will deadlock, if it already
-has locked the #GMutex while calling g_mutex_lock(). Use
+has locked @mutex while calling g_mutex_lock(). Use
#GStaticRecMutex instead, if you need recursive mutexes.
</para>
</note>
called and will immediately return TRUE then.
</para>
+<note>
+<para>
+#GMutex is not recursive, i.e. g_mutex_trylock() will return FALSE,
+if the current thread already has locked @mutex. Use
+#GStaticRecMutex instead, if you need recursive mutexes.
+</para>
+</note>
+
@mutex: a #GMutex
@Returns: TRUE, if @mutex could be locked
<!-- ##### FUNCTION g_static_mutex_lock ##### -->
<para>
-works like g_mutex_lock(), but for a #GStaticMutex.
+Works like g_mutex_lock(), but for a #GStaticMutex.
</para>
@mutex: a #GStaticMutex
<!-- ##### FUNCTION g_static_mutex_trylock ##### -->
<para>
-works like g_mutex_trylock(), but for a #GStaticMutex.
+Works like g_mutex_trylock(), but for a #GStaticMutex.
</para>
@mutex: a #GStaticMutex
<!-- ##### FUNCTION g_static_mutex_unlock ##### -->
<para>
-works like g_mutex_unlock(), but for a #GStaticMutex.
+Works like g_mutex_unlock(), but for a #GStaticMutex.
</para>
@mutex: a #GStaticMutex
<!-- ##### MACRO G_LOCK ##### -->
<para>
-works like g_mutex_lock(), but for a lock defined with #G_LOCK_DEFINE.
+Works like g_mutex_lock(), but for a lock defined with #G_LOCK_DEFINE.
</para>
@name: the name of the lock
<!-- ##### MACRO G_TRYLOCK ##### -->
<para>
-works like g_mutex_trylock(), but for a lock defined with #G_LOCK_DEFINE.
+Works like g_mutex_trylock(), but for a lock defined with #G_LOCK_DEFINE.
</para>
@name: the name of the lock
<!-- ##### MACRO G_UNLOCK ##### -->
<para>
-works like g_mutex_unlock(), but for a lock defined with #G_LOCK_DEFINE.
+Works like g_mutex_unlock(), but for a lock defined with #G_LOCK_DEFINE.
</para>
@name: the name of the lock
<!-- ##### STRUCT GStaticRWLock ##### -->
<para>
+The #GStaticRWLock struct represents a read-write lock. A read-write
+lock can be used for protecting data, that some portions of code only
+read from, while others also write. In such situations it is
+desirable, that several readers can read at once, whereas of course
+only one writer may write at a time. Take a look at the following
+example:
+
+<example>
+<title>An array with access functions</title>
+<programlisting>
+ GStaticRWLock rwlock = G_STATIC_RW_LOCK_INIT;
+
+ GPtrArray *array;
+ gpointer my_array_get (guint index)
+ {
+ gpointer retval = NULL;
+
+ if (!array)
+ return NULL;
+
+ g_static_rw_lock_reader_lock (&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 my_array_get function) simultaneously, whereas the writers (the
+my_array_set function) only will be allowed once a time and only if no
+readers currently access the array. This is because of the potentially
+dangerous resizing of the array. Using that functions is fully
+multi-thread safe now.
</para>
+<para>
+Most of the time the writers should have precedence of readers. That
+means for this implementation, that as soon as a writer wants to lock
+the data, no other reader is allowed to lock the data, whereas of
+course the readers, that already have locked the data are allowed to
+finish their operation. As soon as the last reader unlocks the data,
+the writer will lock it.
+</para>
+
+<para>
+Even though #GStaticRWLock is not opaque, it should only be used with
+the following functions.
+</para>
+
+<para>
+All of the g_static_rw_lock_* functions can also be used, if
+g_thread_init() has not been called.
+</para>
+
+<note>
+<para>
+A read-write lock has a higher overhead as a mutex. For example both
+g_static_rw_lock_reader_lock() and g_static_rw_lock_reader_unlock()
+has to lock and unlock a #GStaticMutex, so it takes at least twice the
+time to lock and unlock a #GStaticRWLock than to lock and unlock a
+#GStaticMutex. So only data structures, that are accessed by multiple
+readers, which keep the lock for a considerable time justify a
+#GStaticRWLock. The above example most probably would fare better with
+a #GStaticMutex.
+</para>
+</note>
+
@mutex:
@read_cond:
@write_cond:
<!-- ##### MACRO G_STATIC_RW_LOCK_INIT ##### -->
<para>
+A #GStaticRWLock must be initialized with this macro, before it can
+be used. This macro can used be to initialize a variable, but it
+cannot be assigned to a variable. In that case you have to use
+g_static_rw_lock_init().
+</para>
+<para>
+<informalexample>
+<programlisting>
+GStaticRWLock my_lock = G_STATIC_RW_LOCK_INIT;
+</programlisting>
+</informalexample>
</para>
<!-- ##### FUNCTION g_static_rw_lock_init ##### -->
<para>
-
+A #GStaticRWLock must be initialized with this function, before it can
+be used. Alternatively you can initialize it with
+#G_STATIC_RW_LOCK_INIT.
</para>
-@lock:
+@lock: a #GStaticRWLock to be initialized
<!-- ##### FUNCTION g_static_rw_lock_reader_lock ##### -->
<para>
+Locks @lock for reading. There may be unlimited concurrent locks for
+reading of a #GStaticRWLock at the same time. If @lock is already
+locked for writing by another thread or if another thread is already
+waiting to lock @lock for writing, this function will block until
+@lock is unlocked by the other writing thread and no other writing
+threads want to lock @lock. This lock has to be unlocked by
+g_static_rw_lock_reader_unlock().
+</para>
+<para>
+#GStaticRWLock in general is not recursive, but as there may be
+unlimited concurrent locks for reading, it effectively is for
+recursive for reading, but for reading only. Locking for writing after
+locking for reading will deadlock, the same holds true for the
+opposite order.
</para>
-@lock:
+@lock: a #GStaticRWLock to lock for reading
<!-- ##### FUNCTION g_static_rw_lock_reader_trylock ##### -->
<para>
-
+Tries to lock @lock for reading. If @lock is already locked for
+writing by another thread or if another thread is already waiting to
+lock @lock for writing, it immediately returns #FALSE. Otherwise it
+locks @lock for reading and returns TRUE. This lock has to be unlocked
+by g_static_rw_lock_reader_unlock().
</para>
-@lock:
-@Returns:
+@lock: a #GStaticRWLock to lock for reading
+@Returns: TRUE, if @lock could be locked for reading
<!-- ##### FUNCTION g_static_rw_lock_reader_unlock ##### -->
<para>
-
+Unlocks @lock. If a thread waits to lock @lock for writing and all
+locks for reading have been unlocked, the waiting thread is woken up
+and can lock @lock for writing.
</para>
-@lock:
+@lock: a #GStaticRWLock to unlock after reading
<!-- ##### FUNCTION g_static_rw_lock_writer_lock ##### -->
<para>
-
+Locks @lock for writing. If @lock is already locked for writing or
+reading by other threads, this function will block until @lock is
+completely unlocked and then lock @lock for writing. While this
+functions waits to lock @lock, no other thread can lock @lock for
+reading. When @lock is locked for writing, no other thread can lock
+@lock (neither for reading nor writing). This lock has to be unlocked
+by g_static_rw_lock_writer_unlock().
</para>
-@lock:
+@lock: a #GStaticRWLock to lock for writing
<!-- ##### FUNCTION g_static_rw_lock_writer_trylock ##### -->
<para>
-
+Tries to lock @lock for writing. If @lock is already locked (for
+either reading or writing) by another thread, it immediately returns
+#FALSE. Otherwise it locks @lock for writing and returns TRUE. This
+lock has to be unlocked by g_static_rw_lock_writer_unlock().
</para>
-@lock:
-@Returns:
+@lock: a #GStaticRWLock to lock for writing
+@Returns: TRUE, if @lock could be locked for writing
<!-- ##### FUNCTION g_static_rw_lock_writer_unlock ##### -->
<para>
-
+Unlocks @lock. If a thread waits to lock @lock for writing and all
+locks for reading have been unlocked, the waiting thread is woken up
+and can lock @lock for writing. If no thread waits to lock @lock for
+writing and threads wait to lock @lock for reading, the waiting
+threads are woken up and can lock @lock for reading.
</para>
-@lock:
+@lock: a #GStaticRWLock to unlock after writing
<!-- ##### FUNCTION g_static_rw_lock_free ##### -->
<para>
+Releases all resources allocated to @lock.
+</para>
+<para>
+You don't have to call this functions for a #GStaticRWLock with an
+unbounded lifetime, i.e. objects declared 'static', but if you have a
+#GStaticRWLock as a member of a structure and the structure is freed,
+you should also free the #GStaticRWLock.
</para>
-@lock:
+@lock: a #GStaticRWLock to be freed
<!-- ##### STRUCT GCond ##### -->
called and will immediately return TRUE then.
</para>
+<para>
+To easily calculate @abs_time a combination of g_get_current_time()
+and g_time_val_add() can be used.
+</para>
+
@cond: a #GCond
@mutex: a #GMutex, that is currently locked
@abs_time: a #GTimeVal, determining the final time
@Returns: the corresponding pointer
-<!-- ##### FUNCTION g_static_private_get_for_thread ##### -->
-<para>
-
-</para>
-
-@private_key:
-@thread:
-@Returns:
-
-
<!-- ##### FUNCTION g_static_private_set ##### -->
<para>
Sets the pointer keyed to @private_key for the current thread and the
current thread ends or sets this pointer again
-<!-- ##### FUNCTION g_static_private_set_for_thread ##### -->
-<para>
-
-</para>
-
-@private_key:
-@thread:
-@data:
-@notify:
-
-
<!-- ##### FUNCTION g_static_private_free ##### -->
<para>
Releases all resources allocated to @private_key.