From 7208b0f183408b4801d5b92f476caac45fec113f Mon Sep 17 00:00:00 2001 From: Sebastian Wilhelmi Date: Wed, 7 Mar 2001 17:36:58 +0000 Subject: [PATCH] C2001-03-07 Sebastian Wilhelmi C2001-03-07 Sebastian Wilhelmi * glib/tmpl/threads.sgml: Completed. VS: ---------------------------------------------------------------------- --- docs/reference/ChangeLog | 4 + docs/reference/glib/tmpl/threads.sgml | 184 ++++++++++++++++++++++++++++++---- 2 files changed, 166 insertions(+), 22 deletions(-) diff --git a/docs/reference/ChangeLog b/docs/reference/ChangeLog index 5fcacd1..ce1c204 100644 --- a/docs/reference/ChangeLog +++ b/docs/reference/ChangeLog @@ -1,3 +1,7 @@ +2001-03-07 Sebastian Wilhelmi + + * glib/tmpl/threads.sgml: Completed. + Wed Mar 7 09:33:27 2001 Tim Janik * gobject/Makefile.am: shuffled rules to avoid excessive diff --git a/docs/reference/glib/tmpl/threads.sgml b/docs/reference/glib/tmpl/threads.sgml index 2e23b2b..68e0585 100644 --- a/docs/reference/glib/tmpl/threads.sgml +++ b/docs/reference/glib/tmpl/threads.sgml @@ -654,7 +654,7 @@ Initializes @mutex. Alternatively you can initialize it with -works like g_mutex_lock(), but for a #GStaticMutex. +Works like g_mutex_lock(), but for a #GStaticMutex. @mutex: a #GStaticMutex @@ -663,7 +663,7 @@ 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. @mutex: a #GStaticMutex @@ -673,7 +673,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. @mutex: a #GStaticMutex @@ -765,7 +765,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. @name: the name of the lock @@ -774,7 +774,7 @@ 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. @name: the name of the lock @@ -784,7 +784,7 @@ 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. @name: the name of the lock @@ -919,9 +919,96 @@ freed, you should also free the #GStaticRecMutex. +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 followin +example: + +An array with access functions + + 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); + } + + + + + +This example shows an array, which can be accessed by many readers +(the my_array_get function) simultaniously, 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 +multithread safe now. + + + +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. + + + +Even though #GStaticRWLoc is not opaque, it should only be used with +the following functions. + +All of the g_static_rw_lock_* functions can also be used, if +g_thread_init() has not been called. + + + + +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. + + + @mutex: @read_cond: @write_cond: @@ -931,75 +1018,128 @@ freed, you should also free the #GStaticRecMutex. +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(). + + + + +GStaticRWLock my_lock = G_STATIC_RW_LOCK_INIT; + + - +A #GStaticRWLock must be initialized with this function, before it can +be used. Alternatively you can initialize it with +#G_STATIC_RW_LOCK_INIT. -@lock: +@lock: a #GStaticRWLock to be initialized +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(). + + +#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. -@lock: +@lock: a #GStaticRWLock to lock for reading - +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(). -@lock: -@Returns: +@lock: a #GStaticRWLock to lock for reading +@Returns: TRUE, if @lock could be locked for reading - +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. -@lock: +@lock: a #GStaticRWLock to unlock after reading - +Locks @lock for writing. If @lock is already locked for writing or +reading by other threads, this function will block until @lock is +completly 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(). -@lock: +@lock: a #GStaticRWLock to lock for writing - +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(). -@lock: -@Returns: +@lock: a #GStaticRWLock to lock for writing +@Returns: TRUE, if @lock could be locked for writing - +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. -@lock: +@lock: a #GStaticRWLock to unlock after writing +Releases all resources allocated to @lock. + + +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. -@lock: +@lock: a #GStaticRWLock to be freed -- 2.7.4