RWLock


Object Hierarchy:

GLib.RWLock GLib.RWLock GLib.RWLock

Description:

[ Version ( since = "2.32" ) ]
[ 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


Namespace: GLib
Package: glib-2.0

Content:

Creation methods:

Methods: