Copyright | Will Thompson Iñaki García Etxebarria and Jonas Platte |
---|---|
License | LGPL-2.1 |
Maintainer | Iñaki García Etxebarria (inaki@blueleaf.cc) |
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
- noRWLock :: Maybe 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
WrappedPtr RWLock Source # | |
Defined in GI.GLib.Structs.RWLock wrappedPtrCalloc :: IO (Ptr RWLock) # wrappedPtrCopy :: RWLock -> IO RWLock # | |
tag ~ AttrSet => Constructible RWLock tag Source # | |
Defined in GI.GLib.Structs.RWLock |
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
or blocks waiting for it, the current
thread 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
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
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