Change the order to match the order in g_thread_create().

2001-02-23  Sebastian Wilhelmi  <wilhelmi@ira.uka.de>

	* gthread.h (struct _GThread): Change the order to match the order
	in g_thread_create().

	* gthread.c (g_static_rec_mutex_lock_full): Also do the right
	thing (behave like 'depth' calls to g_static_rec_mutex_lock) for a
	mutex, that is already locked.

	* glib/tmpl/threads.sgml: Big update. Almost ready.

	* glib/tmpl/async_queues.sgml: Typo.

	* glib/glib-sections.txt: Added g_static_rec_mutex_init,
	g_static_rec_mutex_free, g_static_rw_lock_init,
	g_static_private_init and g_static_private_free.

	* glib/glib-overrides.txt: Added g_thread_yield and g_thread_exit.
This commit is contained in:
Sebastian Wilhelmi
2001-02-23 16:42:48 +00:00
committed by Sebastian Wilhelmi
parent 2632cf94f6
commit 2395a333cc
17 changed files with 478 additions and 159 deletions

View File

@@ -1,3 +1,12 @@
2001-02-23 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread.h (struct _GThread): Change the order to match the order
in g_thread_create().
* gthread.c (g_static_rec_mutex_lock_full): Also do the right
thing (behave like 'depth' calls to g_static_rec_mutex_lock) for a
mutex, that is already locked.
Thu Feb 22 10:31:36 2001 Owen Taylor <otaylor@redhat.com> Thu Feb 22 10:31:36 2001 Owen Taylor <otaylor@redhat.com>
* gmain.c (g_source_remove_poll): Add missing implementation * gmain.c (g_source_remove_poll): Add missing implementation

View File

@@ -1,3 +1,12 @@
2001-02-23 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread.h (struct _GThread): Change the order to match the order
in g_thread_create().
* gthread.c (g_static_rec_mutex_lock_full): Also do the right
thing (behave like 'depth' calls to g_static_rec_mutex_lock) for a
mutex, that is already locked.
Thu Feb 22 10:31:36 2001 Owen Taylor <otaylor@redhat.com> Thu Feb 22 10:31:36 2001 Owen Taylor <otaylor@redhat.com>
* gmain.c (g_source_remove_poll): Add missing implementation * gmain.c (g_source_remove_poll): Add missing implementation

View File

@@ -1,3 +1,12 @@
2001-02-23 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread.h (struct _GThread): Change the order to match the order
in g_thread_create().
* gthread.c (g_static_rec_mutex_lock_full): Also do the right
thing (behave like 'depth' calls to g_static_rec_mutex_lock) for a
mutex, that is already locked.
Thu Feb 22 10:31:36 2001 Owen Taylor <otaylor@redhat.com> Thu Feb 22 10:31:36 2001 Owen Taylor <otaylor@redhat.com>
* gmain.c (g_source_remove_poll): Add missing implementation * gmain.c (g_source_remove_poll): Add missing implementation

View File

@@ -1,3 +1,12 @@
2001-02-23 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread.h (struct _GThread): Change the order to match the order
in g_thread_create().
* gthread.c (g_static_rec_mutex_lock_full): Also do the right
thing (behave like 'depth' calls to g_static_rec_mutex_lock) for a
mutex, that is already locked.
Thu Feb 22 10:31:36 2001 Owen Taylor <otaylor@redhat.com> Thu Feb 22 10:31:36 2001 Owen Taylor <otaylor@redhat.com>
* gmain.c (g_source_remove_poll): Add missing implementation * gmain.c (g_source_remove_poll): Add missing implementation

View File

@@ -1,3 +1,12 @@
2001-02-23 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread.h (struct _GThread): Change the order to match the order
in g_thread_create().
* gthread.c (g_static_rec_mutex_lock_full): Also do the right
thing (behave like 'depth' calls to g_static_rec_mutex_lock) for a
mutex, that is already locked.
Thu Feb 22 10:31:36 2001 Owen Taylor <otaylor@redhat.com> Thu Feb 22 10:31:36 2001 Owen Taylor <otaylor@redhat.com>
* gmain.c (g_source_remove_poll): Add missing implementation * gmain.c (g_source_remove_poll): Add missing implementation

View File

@@ -1,3 +1,12 @@
2001-02-23 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread.h (struct _GThread): Change the order to match the order
in g_thread_create().
* gthread.c (g_static_rec_mutex_lock_full): Also do the right
thing (behave like 'depth' calls to g_static_rec_mutex_lock) for a
mutex, that is already locked.
Thu Feb 22 10:31:36 2001 Owen Taylor <otaylor@redhat.com> Thu Feb 22 10:31:36 2001 Owen Taylor <otaylor@redhat.com>
* gmain.c (g_source_remove_poll): Add missing implementation * gmain.c (g_source_remove_poll): Add missing implementation

View File

@@ -1,3 +1,12 @@
2001-02-23 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread.h (struct _GThread): Change the order to match the order
in g_thread_create().
* gthread.c (g_static_rec_mutex_lock_full): Also do the right
thing (behave like 'depth' calls to g_static_rec_mutex_lock) for a
mutex, that is already locked.
Thu Feb 22 10:31:36 2001 Owen Taylor <otaylor@redhat.com> Thu Feb 22 10:31:36 2001 Owen Taylor <otaylor@redhat.com>
* gmain.c (g_source_remove_poll): Add missing implementation * gmain.c (g_source_remove_poll): Add missing implementation

View File

@@ -1,3 +1,12 @@
2001-02-23 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* gthread.h (struct _GThread): Change the order to match the order
in g_thread_create().
* gthread.c (g_static_rec_mutex_lock_full): Also do the right
thing (behave like 'depth' calls to g_static_rec_mutex_lock) for a
mutex, that is already locked.
Thu Feb 22 10:31:36 2001 Owen Taylor <otaylor@redhat.com> Thu Feb 22 10:31:36 2001 Owen Taylor <otaylor@redhat.com>
* gmain.c (g_source_remove_poll): Add missing implementation * gmain.c (g_source_remove_poll): Add missing implementation

View File

@@ -1,3 +1,15 @@
2001-02-23 Sebastian Wilhelmi <wilhelmi@ira.uka.de>
* glib/tmpl/threads.sgml: Big update. Almost ready.
* glib/tmpl/async_queues.sgml: Typo.
* glib/glib-sections.txt: Added g_static_rec_mutex_init,
g_static_rec_mutex_free, g_static_rw_lock_init,
g_static_private_init and g_static_private_free.
* glib/glib-overrides.txt: Added g_thread_yield and g_thread_exit.
Fri Feb 16 06:52:20 2001 Tim Janik <timj@gtk.org> Fri Feb 16 06:52:20 2001 Tim Janik <timj@gtk.org>
* gobject/tmpl/types.sgml: incorporated huge docu patch from Eric * gobject/tmpl/types.sgml: incorporated huge docu patch from Eric

View File

@@ -91,6 +91,18 @@ GStaticMutex* mutex
GStaticMutex* mutex GStaticMutex* mutex
</FUNCTION> </FUNCTION>
# GThread
<FUNCTION>
<NAME>g_thread_yield</NAME>
<RETURNS>void</RETURNS>
</FUNCTION>
<FUNCTION>
<NAME>g_thread_exit</NAME>
<RETURNS>void</RETURNS>
</FUNCTION>
# G_LOCK_* macros # G_LOCK_* macros
<MACRO> <MACRO>

View File

@@ -479,15 +479,18 @@ G_UNLOCK
<SUBSECTION> <SUBSECTION>
GStaticRecMutex GStaticRecMutex
G_STATIC_REC_MUTEX_INIT G_STATIC_REC_MUTEX_INIT
g_static_rec_mutex_init
g_static_rec_mutex_lock g_static_rec_mutex_lock
g_static_rec_mutex_trylock g_static_rec_mutex_trylock
g_static_rec_mutex_unlock g_static_rec_mutex_unlock
g_static_rec_mutex_lock_full g_static_rec_mutex_lock_full
g_static_rec_mutex_unlock_full g_static_rec_mutex_unlock_full
g_static_rec_mutex_free
<SUBSECTION> <SUBSECTION>
GStaticRWLock GStaticRWLock
G_STATIC_RW_LOCK_INIT G_STATIC_RW_LOCK_INIT
g_static_rw_lock_init
g_static_rw_lock_reader_lock g_static_rw_lock_reader_lock
g_static_rw_lock_reader_trylock g_static_rw_lock_reader_trylock
g_static_rw_lock_reader_unlock g_static_rw_lock_reader_unlock
@@ -514,10 +517,12 @@ g_private_set
<SUBSECTION> <SUBSECTION>
GStaticPrivate GStaticPrivate
G_STATIC_PRIVATE_INIT G_STATIC_PRIVATE_INIT
g_static_private_init
g_static_private_get g_static_private_get
g_static_private_get_for_thread g_static_private_get_for_thread
g_static_private_set g_static_private_set
g_static_private_set_for_thread g_static_private_set_for_thread
g_static_private_free
<SUBSECTION Private> <SUBSECTION Private>
G_THREAD_ECF G_THREAD_ECF

View File

@@ -55,7 +55,7 @@ g_async_queue_unlock()) over multiple queue accessing
instructions. This can be necessary to ensure the integrity of the instructions. This can be necessary to ensure the integrity of the
queue, but should only be used, when really necessary as it can make queue, but should only be used, when really necessary as it can make
your life harder if used unwisely. Normally you should only use the your life harder if used unwisely. Normally you should only use the
locking function variants (those without the suffix _unlocking) locking function variants (those without the suffix _unlocked)
</para> </para>
<!-- ##### SECTION See_Also ##### --> <!-- ##### SECTION See_Also ##### -->

View File

@@ -4,7 +4,8 @@ Threads
<!-- ##### SECTION Short_Description ##### --> <!-- ##### SECTION Short_Description ##### -->
thread abstraction; including mutexes, conditions and thread private data. thread abstraction; including threads, different mutexes, conditions
and thread private data.
<!-- ##### SECTION Long_Description ##### --> <!-- ##### SECTION Long_Description ##### -->
@@ -15,24 +16,37 @@ communication between the involved threads via this shared memory, and
it is bad, because strange things (so called Heisenbugs) might happen, it is bad, because strange things (so called Heisenbugs) might happen,
when the program is not carefully designed. Especially bad is, that due when the program is not carefully designed. Especially bad is, that due
to the concurrent nature of threads no assumptions on the order of to the concurrent nature of threads no assumptions on the order of
execution of different threads can be done unless explictly forced by execution of different threads can be done unless explicitly forced by
the programmer through synchronization primitives. the programmer through synchronization primitives.
</para> </para>
<para> <para>
The aim of the thread related functions in GLib is to provide a The aim of the thread related functions in GLib is to provide a
portable means for writing multithread safe software. There are portable means for writing multithreaded software. There are
primitives for mutexes to protect the access to portions of memory primitives for mutexes to protect the access to portions of memory
(#GMutex, #GStaticMutex, #G_LOCK_DEFINE and friends), there are (#GMutex, #GStaticMutex, #G_LOCK_DEFINE, #GStaticRecMutex and
primitives for condition variables to allow synchronization of threads #GStaticRWLock), there are primitives for condition variables to allow
(#GCond) and finally there are primitives for thread-private data, synchronization of threads (#GCond) and finally there are primitives
that every thread has a private instance of (#GPrivate, for thread-private data, that every thread has a private instance of
#GStaticPrivate). (#GPrivate, #GStaticPrivate). Last but definitely not least there are
primitives to portably create and manage threads (#GThread).
</para> </para>
<!-- ##### SECTION See_Also ##### --> <!-- ##### SECTION See_Also ##### -->
<para> <para>
<variablelist>
<varlistentry>
<term>#GThreadPool</term>
<listitem><para>Thread pools.</para></listitem>
</varlistentry>
<varlistentry>
<term>#GAsyncQueue</term>
<listitem><para>Send asynchronous messages between threads.</para></listitem>
</varlistentry>
</variablelist>
</para> </para>
<!-- ##### MACRO G_THREADS_ENABLED ##### --> <!-- ##### MACRO G_THREADS_ENABLED ##### -->
@@ -58,7 +72,7 @@ This macro is defined, if POSIX style threads are used.
<!-- ##### MACRO G_THREADS_IMPL_SOLARIS ##### --> <!-- ##### MACRO G_THREADS_IMPL_SOLARIS ##### -->
<para> <para>
This macro is defined, if the SOLARIS thread system is used. This macro is defined, if the Solaris thread system is used.
</para> </para>
@@ -74,17 +88,18 @@ however provide one to g_thread_init() to make GLib multithread safe.
<!-- ##### MACRO G_THREAD_ERROR ##### --> <!-- ##### MACRO G_THREAD_ERROR ##### -->
<para> <para>
The error domain of the GLib thread subsystem.
</para> </para>
<!-- ##### ENUM GThreadError ##### --> <!-- ##### ENUM GThreadError ##### -->
<para> <para>
Possible errors of thread related functions.
</para> </para>
@G_THREAD_ERROR_AGAIN: @G_THREAD_ERROR_AGAIN: a thread couldn't be created due to resource
shortage. Try again later.
<!-- ##### STRUCT GThreadFunctions ##### --> <!-- ##### STRUCT GThreadFunctions ##### -->
@@ -142,7 +157,8 @@ really know, what you are doing.
<note> <note>
<para> <para>
g_thread_init() must not be called directly or indirectly as a g_thread_init() must not be called directly or indirectly as a
callback from GLib. callback from GLib. Also no mutexes may be currently locked, while
calling g_thread_init().
</para> </para>
</note> </note>
@@ -182,7 +198,7 @@ libraries.
</note> </note>
@vtable: a function table of type #GThreadFunctions, that provides the @vtable: a function table of type #GThreadFunctions, that provides the
entry points to the thread system to be used. entry points to the thread system to be used
<!-- ##### FUNCTION g_thread_supported ##### --> <!-- ##### FUNCTION g_thread_supported ##### -->
@@ -198,88 +214,169 @@ you can however use it as if it was a function.
</para> </para>
</note> </note>
@Returns: TRUE, if the thread system is initialized. @Returns: TRUE, if the thread system is initialized
<!-- ##### USER_FUNCTION GThreadFunc ##### --> <!-- ##### USER_FUNCTION GThreadFunc ##### -->
<para> <para>
Specifies the type of the @thread_func functions passed to
g_thread_create().
</para> </para>
@value: @value: data supplied to the thread
<!-- ##### ENUM GThreadPriority ##### --> <!-- ##### ENUM GThreadPriority ##### -->
<para> <para>
Specifies the priority of a thread.
</para> </para>
@G_THREAD_PRIORITY_LOW: <note>
@G_THREAD_PRIORITY_NORMAL: <para>
@G_THREAD_PRIORITY_HIGH: It is not guaranteed, that threads with different priorities really
@G_THREAD_PRIORITY_URGENT: behave accordingly. On some systems (e.g. Linux) only root can increase
priorities. On other systems (e.g. Solaris) there doesn't seem to be
different scheduling for different priorities. All in all try to avoid
being dependent on priorities.
</para>
</note>
@G_THREAD_PRIORITY_LOW: a priority lower than normal
@G_THREAD_PRIORITY_NORMAL: the default priority
@G_THREAD_PRIORITY_HIGH: a priority higher than normal
@G_THREAD_PRIORITY_URGENT: the highest priority
<!-- ##### STRUCT GThread ##### --> <!-- ##### STRUCT GThread ##### -->
<para> <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.
</para> </para>
@priority: <note>
@bound: <para>
@joinable: Resources for a joinable thread are not fully released until
g_thread_join() is called for that thread.
</para>
</note>
@joinable: is this thread joinable?
@bound: is this thread bound to a system thread?
@priority: the priority of the thread
<!-- ##### FUNCTION g_thread_create ##### --> <!-- ##### FUNCTION g_thread_create ##### -->
<para> <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>
@thread_func: <para>
@arg: If @joinable is #TRUE, you can wait for this threads termination
@stack_size: calling g_thread_wait(). Otherwise the thread will just disappear, when
@joinable: ready. If @bound is #TRUE, this thread will be scheduled in the system
@bound: scope, otherwise the implementation is free to do scheduling in the
@priority: process scope. The first variant is more expensive resource-wise, but
@error: generally faster. On some systems (e.g. Linux) all threads are bound.
@Returns: </para>
<para>
The new thread executes the function @thread_func with the argument
@arg. 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>
<note>
<para>
It is not guaranteed, that threads with different priorities really
behave accordingly. On some systems (e.g. Linux) only root can increase
priorities. On other systems (e.g. Solaris) there doesn't seem to be
different scheduling for different priorities. All in all try to avoid
being dependent on priorities. Use %G_THREAD_PRIORITY_NORMAL here as a
default.
</para>
</note>
@thread_func: a function to execute in the new thread
@arg: an argument to supply to the new thread
@stack_size: a stack size for the new thread
@joinable: should this thread be joinable?
@bound: should this thread be bound to a system thread?
@priority: a priority for the thread
@error: return location for error.
@Returns: the new #GThread on success
<!-- ##### FUNCTION g_thread_self ##### --> <!-- ##### FUNCTION g_thread_self ##### -->
<para> <para>
This functions returns the #GThread corresponding to the calling thread.
</para> </para>
@Returns: @Returns: the current thread
<!-- ##### FUNCTION g_thread_join ##### --> <!-- ##### FUNCTION g_thread_join ##### -->
<para> <para>
Waits until @thread finishes, i.e. the function @thread_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().
</para> </para>
@thread: @thread: a #GThread to be waited for
<!-- ##### FUNCTION g_thread_set_priority ##### --> <!-- ##### FUNCTION g_thread_set_priority ##### -->
<para> <para>
Change the priority of @thread to @priority.
</para> </para>
@thread: <note>
@priority:
<!-- ##### MACRO g_thread_yield ##### -->
<para> <para>
It is not guaranteed, that threads with different priorities really
behave accordingly. On some systems (e.g. Linux) only root can increase
priorities. On other systems (e.g. Solaris) there doesn't seem to be
different scheduling for different priorities. All in all try to avoid
being dependent on priorities.
</para> </para>
</note>
@thread: a #GThread
@priority: a new priority for @thread
<!-- ##### FUNCTION g_thread_yield ##### -->
<!-- ##### MACRO g_thread_exit ##### -->
<para> <para>
Give way to other threads waiting to be scheduled.
</para> </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>
<!-- ##### 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.
</para>
<note>
<para>
Never call g_thread_exit from within a thread of a #GThreadPool, as
that will mess up the bookkeeping and lead to funny and unwanted
results.
</para>
</note>
<!-- ##### STRUCT GMutex ##### --> <!-- ##### STRUCT GMutex ##### -->
@@ -400,15 +497,15 @@ This function will abort, if g_thread_init() has not been called yet.
</para> </para>
</note> </note>
@Returns: a new #GMutex. @Returns: a new #GMutex
<!-- ##### FUNCTION g_mutex_lock ##### --> <!-- ##### FUNCTION g_mutex_lock ##### -->
<para> <para>
Locks the #GMutex. If the #GMutex is already locked by another thread, Locks @mutex. If @mutex is already locked by another thread, the
the current thread will block until the #GMutex is unlocked by the current thread will block until @mutex is unlocked by the other
other thread. thread.
</para> </para>
<para> <para>
@@ -418,20 +515,20 @@ called and will do nothing then.
<note> <note>
<para> <para>
#GMutex is not guaranteed to be recursive, i.e. a thread might block, #GMutex is not recursive, i.e. a thread will deadlock, if it already
if it already has locked the #GMutex. It will deadlock then, of has locked the #GMutex while calling g_mutex_lock(). Use
course. #GStaticRecMutex instead, if you need recursive mutexes.
</para> </para>
</note> </note>
@mutex: a #GMutex. @mutex: a #GMutex
<!-- ##### FUNCTION g_mutex_trylock ##### --> <!-- ##### FUNCTION g_mutex_trylock ##### -->
<para> <para>
Tries to lock the #GMutex. If the #GMutex is already locked by another Tries to lock @mutex. If @mutex is already locked by another
thread, it immediately returns FALSE. Otherwise it locks the #GMutex thread, it immediately returns FALSE. Otherwise it locks @mutex
and returns TRUE. and returns TRUE.
</para> </para>
@@ -440,29 +537,32 @@ This function can also be used, if g_thread_init() has not yet been
called and will immediately return TRUE then. called and will immediately return TRUE then.
</para> </para>
@mutex: a #GMutex. @mutex: a #GMutex
@Returns: TRUE, if the #GMutex could be locked. @Returns: TRUE, if @mutex could be locked
<!-- ##### FUNCTION g_mutex_unlock ##### --> <!-- ##### FUNCTION g_mutex_unlock ##### -->
<para> <para>
Unlocks the #GMutex. If another thread is blocked in a g_mutex_lock() Unlocks @mutex. If another thread is blocked in a g_mutex_lock() call
call, it will be woken and can lock the #GMutex itself. This function for @mutex, it will be woken and can lock @mutex itself.
can also be used, if g_thread_init() has not yet been called and will
do nothing then.
</para> </para>
@mutex: a #GMutex. <para>
This function can also be used, if g_thread_init() has not yet been
called and will do nothing then.
</para>
@mutex: a #GMutex
<!-- ##### FUNCTION g_mutex_free ##### --> <!-- ##### FUNCTION g_mutex_free ##### -->
<para> <para>
Destroys the #GMutex. Destroys @mutex.
</para> </para>
@mutex: a #GMutex. @mutex: a #GMutex
<!-- ##### STRUCT GStaticMutex ##### --> <!-- ##### STRUCT GStaticMutex ##### -->
@@ -474,17 +574,6 @@ but can be defined at compile-time. Here is a shorter, easier and
safer version of our give_me_next_number() example: safer version of our give_me_next_number() example:
</para> </para>
<para>
Sometimes you would like to dynamically create a mutex. If you don't
want to require prior calling to g_thread_init(), because your code
should also be usable in non-threaded programs, you are not able to
use g_mutex_new() and thus #GMutex, as that requires a prior call to
g_thread_init(). In theses cases you can also use a #GStaticMutex. It
must be initialized with g_static_mutex_init() before using it and
freed with with g_static_mutex_free() when not needed anymore to free
up any allocated recourses.
</para>
<para> <para>
<example> <example>
<title>Using GStaticMutex to simplify thread-safe programming</title> <title>Using GStaticMutex to simplify thread-safe programming</title>
@@ -504,14 +593,26 @@ up any allocated recourses.
</example> </example>
</para> </para>
<para>
Sometimes you would like to dynamically create a mutex. If you don't
want to require prior calling to g_thread_init(), because your code
should also be usable in non-threaded programs, you are not able to
use g_mutex_new() and thus #GMutex, as that requires a prior call to
g_thread_init(). In theses cases you can also use a #GStaticMutex. It
must be initialized with g_static_mutex_init() before using it and
freed with with g_static_mutex_free() when not needed anymore to free
up any allocated recourses.
</para>
<para> <para>
Even though #GStaticMutex is not opaque, it should only be used with Even though #GStaticMutex is not opaque, it should only be used with
the following functions, as it is defined differently on different the following functions, as it is defined differently on different
platforms. platforms.
</para> </para>
<para>All of the g_static_mutex_* functions can also be used, if <para>
g_thread_init() has not yet. All of the g_static_mutex_* functions can also be used, if
g_thread_init() has not yet been called.
</para> </para>
<note> <note>
@@ -533,24 +634,22 @@ g_static_mutex_init().
</para> </para>
<para> <para>
<example> <informalexample>
<title>Initializing a GStaticMutext</title>
<programlisting> <programlisting>
GStaticMutex my_mutex = G_STATIC_MUTEX_INIT; GStaticMutex my_mutex = G_STATIC_MUTEX_INIT;
</programlisting> </programlisting>
</example> </informalexample>
</para> </para>
<!-- ##### FUNCTION g_static_mutex_init ##### --> <!-- ##### FUNCTION g_static_mutex_init ##### -->
<para> <para>
A #GStaticMutex must be initialized with this function, before it can Initializes @mutex. Alternatively you can initialize it with
be used. Alternatively you can initialize it with
#G_STATIC_MUTEX_INIT. #G_STATIC_MUTEX_INIT.
</para> </para>
@mutex: a #GStaticMutex to be initialized. @mutex: a #GStaticMutex to be initialized
<!-- ##### FUNCTION g_static_mutex_lock ##### --> <!-- ##### FUNCTION g_static_mutex_lock ##### -->
@@ -558,7 +657,7 @@ be used. Alternatively you can initialize it with
works like g_mutex_lock(), but for a #GStaticMutex. works like g_mutex_lock(), but for a #GStaticMutex.
</para> </para>
@mutex: a #GStaticMutex. @mutex: a #GStaticMutex
<!-- ##### FUNCTION g_static_mutex_trylock ##### --> <!-- ##### FUNCTION g_static_mutex_trylock ##### -->
@@ -567,8 +666,8 @@ works like g_mutex_lock(), but for a #GStaticMutex.
works like g_mutex_trylock(), but for a #GStaticMutex. works like g_mutex_trylock(), but for a #GStaticMutex.
</para> </para>
@mutex: a #GStaticMutex. @mutex: a #GStaticMutex
@Returns: TRUE, if the #GStaticMutex could be locked. @Returns: TRUE, if the #GStaticMutex could be locked
<!-- ##### FUNCTION g_static_mutex_unlock ##### --> <!-- ##### FUNCTION g_static_mutex_unlock ##### -->
@@ -577,7 +676,7 @@ works like g_mutex_trylock(), but for a #GStaticMutex.
works like g_mutex_unlock(), but for a #GStaticMutex. works like g_mutex_unlock(), but for a #GStaticMutex.
</para> </para>
@mutex: a #GStaticMutex. @mutex: a #GStaticMutex
<!-- ##### FUNCTION g_static_mutex_get_mutex ##### --> <!-- ##### FUNCTION g_static_mutex_get_mutex ##### -->
@@ -585,23 +684,26 @@ works like g_mutex_unlock(), but for a #GStaticMutex.
<para> <para>
For some operations (like g_cond_wait()) you must have a #GMutex For some operations (like g_cond_wait()) you must have a #GMutex
instead of a #GStaticMutex. This function will return the instead of a #GStaticMutex. This function will return the
corresponding #GMutex for every #GStaticMutex. corresponding #GMutex for @mutex.
</para> </para>
@mutex: a #GStaticMutex. @mutex: a #GStaticMutex
@Returns: the corresponding #GMutex. @Returns: the #GMutex corresponding to @mutex
<!-- ##### FUNCTION g_static_mutex_free ##### --> <!-- ##### FUNCTION g_static_mutex_free ##### -->
<para> <para>
Releases all resources allocated to a #GStaticMutex. You don't have to Releases all resources allocated to @mutex.
call this functions for a #GStaticMutex with an unbounded lifetime,
i.e. objects declared 'static', but if you have a #GStaticMutex as a
member of a structure and the structure is freed, you should also free
the #GStaticMutex.
</para> </para>
@mutex: a #GStaticMutex. <para>
You don't have to call this functions for a #GStaticMutex with an
unbounded lifetime, i.e. objects declared 'static', but if you have a
#GStaticMutex as a member of a structure and the structure is freed,
you should also free the #GStaticMutex.
</para>
@mutex: a #GStaticMutex to be freed
<!-- ##### MACRO G_LOCK_DEFINE ##### --> <!-- ##### MACRO G_LOCK_DEFINE ##### -->
@@ -610,8 +712,8 @@ the #GStaticMutex.
The G_LOCK_* macros provide a convenient interface to #GStaticMutex The G_LOCK_* macros provide a convenient interface to #GStaticMutex
with the advantage that they will expand to nothing in programs with the advantage that they will expand to nothing in programs
compiled against a thread-disabled GLib, saving code and memory compiled against a thread-disabled GLib, saving code and memory
there. #G_LOCK_DEFINE defines a lock. It can occur, where variable there. #G_LOCK_DEFINE defines a lock. It can appear, where variable
definitions may occur in programs, i.e. in the first block of a definitions may appear in programs, i.e. in the first block of a
function or outside of functions. The @name parameter will be mangled function or outside of functions. The @name parameter will be mangled
to get the name of the #GStaticMutex. This means, that you can use to get the name of the #GStaticMutex. This means, that you can use
names of existing variables as the parameter, e.g. the name of the names of existing variables as the parameter, e.g. the name of the
@@ -639,7 +741,7 @@ int give_me_next_number ()
</example> </example>
</para> </para>
@name: the name of the lock. @name: the name of the lock
<!-- ##### MACRO G_LOCK_DEFINE_STATIC ##### --> <!-- ##### MACRO G_LOCK_DEFINE_STATIC ##### -->
@@ -648,7 +750,7 @@ int give_me_next_number ()
This works like #G_LOCK_DEFINE, but it creates a static object. This works like #G_LOCK_DEFINE, but it creates a static object.
</para> </para>
@name: the name of the lock. @name: the name of the lock
<!-- ##### MACRO G_LOCK_EXTERN ##### --> <!-- ##### MACRO G_LOCK_EXTERN ##### -->
@@ -657,7 +759,7 @@ This works like #G_LOCK_DEFINE, but it creates a static object.
This declares a lock, that is defined with #G_LOCK_DEFINE in another module. This declares a lock, that is defined with #G_LOCK_DEFINE in another module.
</para> </para>
@name: the name of the lock. @name: the name of the lock
<!-- ##### MACRO G_LOCK ##### --> <!-- ##### MACRO G_LOCK ##### -->
@@ -666,7 +768,7 @@ This declares a lock, that is defined with #G_LOCK_DEFINE in another module.
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> </para>
@name: the name of the lock. @name: the name of the lock
<!-- ##### MACRO G_TRYLOCK ##### --> <!-- ##### MACRO G_TRYLOCK ##### -->
@@ -675,8 +777,8 @@ works like g_mutex_lock(), but for a lock defined with #G_LOCK_DEFINE.
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> </para>
@name: the name of the lock. @name: the name of the lock
@Returns: TRUE, if the lock could be locked. @Returns: TRUE, if the lock could be locked
<!-- ##### MACRO G_UNLOCK ##### --> <!-- ##### MACRO G_UNLOCK ##### -->
@@ -685,12 +787,28 @@ works like g_mutex_trylock(), but for a lock defined with #G_LOCK_DEFINE.
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> </para>
@name: the name of the lock. @name: the name of the lock
<!-- ##### STRUCT GStaticRecMutex ##### --> <!-- ##### STRUCT GStaticRecMutex ##### -->
<para> <para>
A #GStaticRecMutex works like a #GStaticMutex, but it can be locked
multiple times by one thread. If you enter it n times, however, you
have to unlock it n times again to let other threads lock it. An
exception is the function g_static_rec_mutex_unlock_full(), that
allows you to unlock a #GStaticRecMutex completely returning the depth,
i.e. the number of times this mutex was locked. The depth can later be
used to restore the state by calling g_static_rec_mutex_lock_full().
</para>
<para>
Even though #GStaticRecMutex is not opaque, it should only be used with
the following functions.
</para>
<para>
All of the g_static_rec_mutex_* functions can also be used, if
g_thread_init() has not been called.
</para> </para>
@mutex: @mutex:
@@ -699,52 +817,104 @@ works like g_mutex_unlock(), but for a lock defined with #G_LOCK_DEFINE.
<!-- ##### MACRO G_STATIC_REC_MUTEX_INIT ##### --> <!-- ##### MACRO G_STATIC_REC_MUTEX_INIT ##### -->
<para> <para>
A #GStaticRecMutex must be initialized with this macro, before it can
be used. This macro can used be to initialize a variable, but it
cannot be assigned to a variable. In that case you have to use
g_static_rec_mutex_init().
</para> </para>
<para>
<informalexample>
<programlisting>
GStaticRecMutex my_mutex = G_STATIC_REC_MUTEX_INIT;
</programlisting>
</informalexample>
</para>
<!-- ##### FUNCTION g_static_rec_mutex_init ##### -->
<para>
A #GStaticRecMutex must be initialized with this function, before it
can be used. Alternatively you can initialize it with
#G_STATIC_REC_MUTEX_INIT.
</para>
@mutex: a #GStaticRecMutex to be initialized
<!-- ##### FUNCTION g_static_rec_mutex_lock ##### --> <!-- ##### FUNCTION g_static_rec_mutex_lock ##### -->
<para> <para>
Locks @mutex. If @mutex is already locked by another thread, the
current thread will block until @mutex is unlocked by the other
thread. If @mutex is already locked by the calling thread, this
functions increases the depth of @mutex and returns immediately.
</para> </para>
@mutex: @mutex: a #GStaticRecMutex to lock
<!-- ##### FUNCTION g_static_rec_mutex_trylock ##### --> <!-- ##### FUNCTION g_static_rec_mutex_trylock ##### -->
<para> <para>
Tries to lock @mutex. If @mutex is already locked by another thread,
it immediately returns #FALSE. Otherwise it locks @mutex and returns
#TRUE. If @mutex is already locked by the calling thread, this
functions increases the depth of @mutex and immediately returns #TRUE.
</para> </para>
@mutex: @mutex: a #GStaticRecMutex to lock
@Returns: @Returns: TRUE, if @mutex could be locked
<!-- ##### FUNCTION g_static_rec_mutex_unlock ##### --> <!-- ##### FUNCTION g_static_rec_mutex_unlock ##### -->
<para> <para>
Unlocks @mutex. Another threads can, however, only lock @mutex when it
has been unlocked as many times, as it had been locked before. If
@mutex is completely unlocked and another thread is blocked in a
g_static_rec_mutex_lock() call for @mutex, it will be woken and can
lock @mutex itself.
</para> </para>
@mutex: @mutex: a #GStaticRecMutex to unlock
<!-- ##### FUNCTION g_static_rec_mutex_lock_full ##### --> <!-- ##### FUNCTION g_static_rec_mutex_lock_full ##### -->
<para> <para>
Works like calling g_static_rec_mutex_lock() for @mutex n times.
</para> </para>
@mutex: @mutex: a #GStaticRecMutex to lock
@depth: @depth: number of times this mutex has to be unlocked to be completely unlocked
<!-- ##### FUNCTION g_static_rec_mutex_unlock_full ##### --> <!-- ##### FUNCTION g_static_rec_mutex_unlock_full ##### -->
<para> <para>
Completely unlocks @mutex. If another thread is blocked in a
g_static_rec_mutex_lock() call for @mutex, it will be woken and can
lock @mutex itself. This function returns the number of times, that
@mutex has been locked by the current thread. To restore the state
before the call to g_static_rec_mutex_unlock_full() you can call
g_static_rec_mutex_lock_full() with the depth returned by this
function.
</para> </para>
@mutex: @mutex: a #GStaticRecMutex to completely unlock
@Returns: @Returns: number of times @mutex has been locked by the current thread
<!-- ##### FUNCTION g_static_rec_mutex_free ##### -->
<para>
Releases all resources allocated to a #GStaticRecMutex.
</para>
<para>
You don't have to call this functions for a #GStaticRecMutex with an
unbounded lifetime, i.e. objects declared 'static', but if you have a
#GStaticRecMutex as a member of a structure and the structure is
freed, you should also free the #GStaticRecMutex.
</para>
@mutex: a #GStaticRecMutex to be freed
<!-- ##### STRUCT GStaticRWLock ##### --> <!-- ##### STRUCT GStaticRWLock ##### -->
@@ -766,6 +936,14 @@ works like g_mutex_unlock(), but for a lock defined with #G_LOCK_DEFINE.
<!-- ##### FUNCTION g_static_rw_lock_init ##### -->
<para>
</para>
@lock:
<!-- ##### FUNCTION g_static_rw_lock_reader_lock ##### --> <!-- ##### FUNCTION g_static_rw_lock_reader_lock ##### -->
<para> <para>
@@ -903,7 +1081,7 @@ Creates a new #GCond. This function will abort, if g_thread_init()
has not been called yet. has not been called yet.
</para> </para>
@Returns: a new #GCond. @Returns: a new #GCond
<!-- ##### FUNCTION g_cond_signal ##### --> <!-- ##### FUNCTION g_cond_signal ##### -->
@@ -918,7 +1096,7 @@ This function can also be used, if g_thread_init() has
not yet been called and will do nothing then. not yet been called and will do nothing then.
</para> </para>
@cond: a #GCond. @cond: a #GCond
<!-- ##### FUNCTION g_cond_broadcast ##### --> <!-- ##### FUNCTION g_cond_broadcast ##### -->
@@ -934,14 +1112,14 @@ This function can also be used, if g_thread_init() has
not yet been called and will do nothing then. not yet been called and will do nothing then.
</para> </para>
@cond: a #GCond. @cond: a #GCond
<!-- ##### FUNCTION g_cond_wait ##### --> <!-- ##### FUNCTION g_cond_wait ##### -->
<para> <para>
Waits until this thread is woken up on the #GCond. The #GMutex is Waits until this thread is woken up on @cond. The @mutex is unlocked
unlocked before falling asleep and locked again before resuming. before falling asleep and locked again before resuming.
</para> </para>
<para> <para>
@@ -949,15 +1127,15 @@ This function can also be used, if g_thread_init() has not yet been
called and will immediately return then. called and will immediately return then.
</para> </para>
@cond: a #GCond. @cond: a #GCond
@mutex: the #GMutex, that is currently locked. @mutex: a #GMutex, that is currently locked
<!-- ##### FUNCTION g_cond_timed_wait ##### --> <!-- ##### FUNCTION g_cond_timed_wait ##### -->
<para> <para>
Waits until this thread is woken up on the #GCond, but not longer than Waits until this thread is woken up on @cond, but not longer than
until the time, that is specified by @abs_time. The #GMutex is until the time, that is specified by @abs_time. The @mutex is
unlocked before falling asleep and locked again before resuming. unlocked before falling asleep and locked again before resuming.
</para> </para>
@@ -970,10 +1148,10 @@ This function can also be used, if g_thread_init() has not yet been
called and will immediately return TRUE then. called and will immediately return TRUE then.
</para> </para>
@cond: a #GCond. @cond: a #GCond
@mutex: the #GMutex, that is currently locked. @mutex: a #GMutex, that is currently locked
@abs_time: a #GTimeVal, determining the final time. @abs_time: a #GTimeVal, determining the final time
@Returns: TRUE, if the thread is woken up in time. @Returns: TRUE, if the thread is woken up in time
<!-- ##### FUNCTION g_cond_free ##### --> <!-- ##### FUNCTION g_cond_free ##### -->
@@ -982,7 +1160,7 @@ called and will immediately return TRUE then.
Destroys the #GCond. Destroys the #GCond.
</para> </para>
@cond: a #GCond. @cond: a #GCond
<!-- ##### STRUCT GPrivate ##### --> <!-- ##### STRUCT GPrivate ##### -->
@@ -1048,15 +1226,15 @@ destructor is called with this pointer as the argument.
<note> <note>
<para> <para>
The @destructor is working quite differently from @notify in @destructor is working quite differently from @notify in
g_static_private_set(). g_static_private_set().
</para> </para>
</note> </note>
<note> <note>
<para> <para>
A #GPrivate can not be destroyed. Reuse it instead, if you can to A #GPrivate can not be freed. Reuse it instead, if you can to avoid
avoid shortage. shortage or use #GStaticPrivate.
</para> </para>
</note> </note>
@@ -1067,8 +1245,8 @@ This function will abort, if g_thread_init() has not been called yet.
</note> </note>
@destructor: a function to handle the data keyed to #GPrivate, when a @destructor: a function to handle the data keyed to #GPrivate, when a
thread ends. thread ends
@Returns: @Returns: a new #GPrivate
<!-- ##### FUNCTION g_private_get ##### --> <!-- ##### FUNCTION g_private_get ##### -->
@@ -1084,8 +1262,8 @@ This function can also be used, if g_thread_init() has not yet been
called and will return the value of @private_key casted to #gpointer then. called and will return the value of @private_key casted to #gpointer then.
</para> </para>
@private_key: a #GPrivate. @private_key: a #GPrivate
@Returns: the corresponding pointer. @Returns: the corresponding pointer
<!-- ##### FUNCTION g_private_set ##### --> <!-- ##### FUNCTION g_private_set ##### -->
@@ -1099,8 +1277,8 @@ This function can also be used, if g_thread_init() has not yet been
called and will set @private_key to @data casted to #GPrivate* then. called and will set @private_key to @data casted to #GPrivate* then.
</para> </para>
@private_key: a #GPrivate. @private_key: a #GPrivate
@data: the new pointer. @data: the new pointer
<!-- ##### STRUCT GStaticPrivate ##### --> <!-- ##### STRUCT GStaticPrivate ##### -->
@@ -1153,6 +1331,15 @@ GStaticPrivate my_private = G_STATIC_PRIVATE_INIT;
<!-- ##### FUNCTION g_static_private_init ##### -->
<para>
Initializes @private_key. Alternatively you can initialize it with
#G_STATIC_PRIVATE_INIT.
</para>
@private_key: a #GStaticPrivate to be initialized
<!-- ##### FUNCTION g_static_private_get ##### --> <!-- ##### FUNCTION g_static_private_get ##### -->
<para> <para>
Works like g_private_get() only for a #GStaticPrivate. Works like g_private_get() only for a #GStaticPrivate.
@@ -1162,8 +1349,8 @@ Works like g_private_get() only for a #GStaticPrivate.
This function also works, if g_thread_init() has not yet been called. This function also works, if g_thread_init() has not yet been called.
</para> </para>
@private_key: a #GStaticPrivate. @private_key: a #GStaticPrivate
@Returns: the corresponding pointer. @Returns: the corresponding pointer
<!-- ##### FUNCTION g_static_private_get_for_thread ##### --> <!-- ##### FUNCTION g_static_private_get_for_thread ##### -->
@@ -1192,15 +1379,15 @@ called g_thread_init().
<note> <note>
<para> <para>
The @notify is working quite differently from @destructor in @notify is working quite differently from @destructor in
g_private_new(). g_private_new().
</para> </para>
</note> </note>
@private_key: a #GStaticPrivate. @private_key: a #GStaticPrivate
@data: the new pointer. @data: the new pointer
@notify: a function to be called with the pointer, whenever the @notify: a function to be called with the pointer, whenever the
current thread ends or sets this pointer again. current thread ends or sets this pointer again
<!-- ##### FUNCTION g_static_private_set_for_thread ##### --> <!-- ##### FUNCTION g_static_private_set_for_thread ##### -->
@@ -1214,3 +1401,18 @@ current thread ends or sets this pointer again.
@notify: @notify:
<!-- ##### FUNCTION g_static_private_free ##### -->
<para>
Releases all resources allocated to @private_key.
</para>
<para>
You don't have to call this functions for a #GStaticPrivate with an
unbounded lifetime, i.e. objects declared 'static', but if you have a
#GStaticPrivate as a member of a structure and the structure is freed,
you should also free the #GStaticPrivate.
</para>
@private_key: a #GStaticPrivate to be freed

View File

@@ -292,13 +292,21 @@ void
g_static_rec_mutex_lock_full (GStaticRecMutex *mutex, g_static_rec_mutex_lock_full (GStaticRecMutex *mutex,
guint depth) guint depth)
{ {
GSystemThread self;
g_return_if_fail (mutex); g_return_if_fail (mutex);
if (!g_thread_supported ()) if (!g_thread_supported ())
return; return;
G_THREAD_UF (thread_self, (&self));
if (g_system_thread_equal (self, mutex->owner))
{
mutex->depth += depth;
return;
}
g_static_mutex_lock (&mutex->mutex); g_static_mutex_lock (&mutex->mutex);
G_THREAD_UF (thread_self, (&mutex->owner)); g_system_thread_assign (mutex->owner, self);
mutex->depth = depth; mutex->depth = depth;
} }

View File

@@ -56,9 +56,9 @@ typedef enum
typedef struct _GThread GThread; typedef struct _GThread GThread;
struct _GThread struct _GThread
{ {
GThreadPriority priority;
gboolean bound;
gboolean joinable; gboolean joinable;
gboolean bound;
GThreadPriority priority;
}; };
typedef struct _GMutex GMutex; typedef struct _GMutex GMutex;

View File

@@ -292,13 +292,21 @@ void
g_static_rec_mutex_lock_full (GStaticRecMutex *mutex, g_static_rec_mutex_lock_full (GStaticRecMutex *mutex,
guint depth) guint depth)
{ {
GSystemThread self;
g_return_if_fail (mutex); g_return_if_fail (mutex);
if (!g_thread_supported ()) if (!g_thread_supported ())
return; return;
G_THREAD_UF (thread_self, (&self));
if (g_system_thread_equal (self, mutex->owner))
{
mutex->depth += depth;
return;
}
g_static_mutex_lock (&mutex->mutex); g_static_mutex_lock (&mutex->mutex);
G_THREAD_UF (thread_self, (&mutex->owner)); g_system_thread_assign (mutex->owner, self);
mutex->depth = depth; mutex->depth = depth;
} }

View File

@@ -56,9 +56,9 @@ typedef enum
typedef struct _GThread GThread; typedef struct _GThread GThread;
struct _GThread struct _GThread
{ {
GThreadPriority priority;
gboolean bound;
gboolean joinable; gboolean joinable;
gboolean bound;
GThreadPriority priority;
}; };
typedef struct _GMutex GMutex; typedef struct _GMutex GMutex;