Copyright | Will Thompson Iñaki García Etxebarria and Jonas Platte |
---|---|
License | LGPL-2.1 |
Maintainer | Iñaki García Etxebarria |
Safe Haskell | None |
Language | Haskell2010 |
The GRWLock struct is an opaque data structure to represent a
reader-writer lock. It is similar to a Mutex
in that it allows
multiple threads to coordinate access to a shared resource.
The difference to a mutex is that a reader-writer lock discriminates
between read-only ('reader') and full ('writer') access. While only
one thread at a time is allowed write access (by holding the 'writer'
lock via rWLockWriterLock
), multiple threads can gain
simultaneous read-only access (by holding the 'reader' lock via
rWLockReaderLock
).
It is unspecified whether readers or writers have priority in acquiring the lock when a reader already holds the lock and a writer is queued to acquire it.
Here is an example for an array with access functions:
C code
GRWLock lock; GPtrArray *array; gpointer my_array_get (guint index) { gpointer retval = NULL; if (!array) return NULL; g_rw_lock_reader_lock (&lock); if (index < array->len) retval = g_ptr_array_index (array, index); g_rw_lock_reader_unlock (&lock); return retval; } void my_array_set (guint index, gpointer data) { g_rw_lock_writer_lock (&lock); 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_rw_lock_writer_unlock (&lock); }
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) will only be allowed one at 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.
If a RWLock
is allocated in static storage then it can be used
without initialisation. Otherwise, you should call
rWLockInit
on it and rWLockClear
when done.
A GRWLock should only be accessed with the g_rw_lock_ functions.
Since: 2.32
Synopsis
- newtype RWLock = RWLock (ManagedPtr RWLock)
- newZeroRWLock :: MonadIO m => m RWLock
- rWLockClear :: (HasCallStack, MonadIO m) => RWLock -> m ()
- rWLockInit :: (HasCallStack, MonadIO m) => RWLock -> m ()
- rWLockReaderLock :: (HasCallStack, MonadIO m) => RWLock -> m ()
- rWLockReaderTrylock :: (HasCallStack, MonadIO m) => RWLock -> m Bool
- rWLockReaderUnlock :: (HasCallStack, MonadIO m) => RWLock -> m ()
- rWLockWriterLock :: (HasCallStack, MonadIO m) => RWLock -> m ()
- rWLockWriterTrylock :: (HasCallStack, MonadIO m) => RWLock -> m Bool
- rWLockWriterUnlock :: (HasCallStack, MonadIO m) => RWLock -> m ()
Exported types
Memory-managed wrapper type.
Instances
Eq RWLock Source # | |
ManagedPtrNewtype RWLock Source # | |
Defined in GI.GLib.Structs.RWLock toManagedPtr :: RWLock -> ManagedPtr RWLock # | |
BoxedPtr RWLock Source # | |
Defined in GI.GLib.Structs.RWLock boxedPtrCopy :: RWLock -> IO RWLock # boxedPtrFree :: RWLock -> IO () # | |
CallocPtr RWLock Source # | |
Defined in GI.GLib.Structs.RWLock boxedPtrCalloc :: IO (Ptr RWLock) # | |
tag ~ 'AttrSet => Constructible RWLock tag Source # | |
Defined in GI.GLib.Structs.RWLock |
Methods
Overloaded methods
clear
:: (HasCallStack, MonadIO m) | |
=> RWLock |
|
-> m () |
Frees the resources allocated to a lock with rWLockInit
.
This function should not be used with a RWLock
that has been
statically allocated.
Calling rWLockClear
when any thread holds the lock
leads to undefined behaviour.
Sine: 2.32
init
:: (HasCallStack, MonadIO m) | |
=> RWLock |
|
-> m () |
Initializes a RWLock
so that it can be used.
This function is useful to initialize a lock that has been allocated on the stack, or as part of a larger structure. It is not necessary to initialise a reader-writer lock that has been statically allocated.
C code
typedef struct { GRWLock l; ... } Blob; Blob *b; b = g_new (Blob, 1); g_rw_lock_init (&b->l);
To undo the effect of rWLockInit
when a lock is no longer
needed, use rWLockClear
.
Calling rWLockInit
on an already initialized RWLock
leads
to undefined behaviour.
Since: 2.32
readerLock
:: (HasCallStack, MonadIO m) | |
=> RWLock |
|
-> m () |
Obtain a read lock on rwLock
. If another thread currently holds
the write lock on rwLock
, the current thread will block. If another thread
does not hold the write lock, but is waiting for it, it is implementation
defined whether the reader or writer will block. Read locks can be taken
recursively.
It is implementation-defined how many threads are allowed to hold read locks on the same lock simultaneously. If the limit is hit, or if a deadlock is detected, a critical warning will be emitted.
Since: 2.32
readerTrylock
:: (HasCallStack, MonadIO m) | |
=> RWLock |
|
-> m Bool | Returns: |
Tries to obtain a read lock on rwLock
and returns True
if
the read lock was successfully obtained. Otherwise it
returns False
.
Since: 2.32
readerUnlock
:: (HasCallStack, MonadIO m) | |
=> RWLock |
|
-> m () |
Release a read lock on rwLock
.
Calling rWLockReaderUnlock
on a lock that is not held
by the current thread leads to undefined behaviour.
Since: 2.32
writerLock
:: (HasCallStack, MonadIO m) | |
=> RWLock |
|
-> m () |
Obtain a write lock on rwLock
. If any thread already holds
a read or write lock on rwLock
, the current thread will block
until all other threads have dropped their locks on rwLock
.
Since: 2.32
writerTrylock
:: (HasCallStack, MonadIO m) | |
=> RWLock |
|
-> m Bool | Returns: |
Tries to obtain a write lock on rwLock
. If any other thread holds
a read or write lock on rwLock
, it immediately returns False
.
Otherwise it locks rwLock
and returns True
.
Since: 2.32
writerUnlock
:: (HasCallStack, MonadIO m) | |
=> RWLock |
|
-> m () |
Release a write lock on rwLock
.
Calling rWLockWriterUnlock
on a lock that is not held
by the current thread leads to undefined behaviour.
Since: 2.32