RWLock
Object Hierarchy:
Description:
[ CCode ( destroy_function = "g_rw_lock_clear" , has_type_id = false ) ]
public struct RWLock
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 writer_lock), multiple threads can gain simultaneous read-only access (by holding the 'reader' lock via reader_lock).
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:
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
RWLock on it and g_rw_lock_clear
when done.
A GRWLock should only be accessed with the g_rw_lock_ functions.
Example: RW-Locks:
public class Context : Object {
// Lock used to protect data:
private RWLock rwlock = RWLock ();
// Shared Data:
private HashTable<string, string> users = new HashTable<string, string> (str_hash, str_equal);
private List<string> messages = new List<string> ();
public Context () {
users.insert ("root", "123");
users.insert ("mean", "abc");
users.insert ("square", "xyz");
}
private bool worker_func (string username, string password, string message) {
// Login:
rwlock.reader_lock ();
string? stored_pw = users.lookup (username);
rwlock.reader_unlock ();
if (stored_pw == null || stored_pw != password) {
print ("%s: Invalid user name or password\n", username);
return false;
}
// Read all messages:
rwlock.reader_lock ();
messages.foreach ((str) => {
print ("%s: %s\n", username, str);
});
rwlock.reader_unlock ();
// Share a message:
rwlock.writer_lock ();
messages.append (message);
rwlock.writer_unlock ();
return true;
}
public void run () {
Thread<bool> worker1 = new Thread<bool> ("worker-1", () => {
string username = "root";
string password = "123";
string message = "roots message";
return worker_func (username, password, message);
});
Thread<bool> worker2 = new Thread<bool> ("worker-2", () => {
string username = "mean";
string password = "abc";
string message = "abcs message";
return worker_func (username, password, message);
});
Thread<bool> worker3 = new Thread<bool> ("worker-3", () => {
string username = "square";
string password = "xyz";
string message = "squares message";
return worker_func (username, password, message);
});
worker1.join ();
worker2.join ();
worker3.join ();
}
public static int main (string[] args) {
if (Thread.supported () == false) {
print ("Threads are not supported.\n");
return 0;
}
// Output:
// ``mean: squares message``
// ``root: squares message``
// ``root: abcs message``
// OR
// ``square: abcs message``
// ``square: roots message``
// OR
// ``root: squares message``
// ``mean: squares message``
// OR
// ``square: abcs message``
// OR
// ...
Context context = new Context ();
context.run ();
return 0;
}
}
valac --target-glib 2.32 GLib.RWLock.vala