14: Synchronization - royal-lang/rl GitHub Wiki
Synchronization
Synchronization or mutexes are available in Royal using the sync keyword.
It's inherently made to avoid deadlocks etc. by allowing multiple objects to be locked etc.
sync // Global synchronization
{
}
sync (OBJECT) // Or just: sync object
{
}
sync (OBJECT1, OBJECT2)
{
}
Example:
sync
{
sharedCounter++;
}
sync foo
{
foo.update();
}
Avoiding deadlocks can be done by using multiple synchronization objects.
Wrong:
sync foo
{
sync bar
{
foo.update(bar); // Possible deadlock
}
}
Okay: (Royal will actually force this upon you if you attempt to directly synchronize another object.)
sync foo,bar
{
foo.update(bar);
}
You can also set a ref struct to be synchronized which will make sure all functions in it are synchronized.
ref:sync struct Foo
{
private:
var decimal _bar;
public:
fn update()
{
_bar++;
}
}
...
var foo @= Foo;
// Wrong:
sync foo
{
foo.update();
}
// Correct:
foo.update();
Shared
shared is a type attribute. A shared type will be checked by the compiler on every usage of it to make sure it's used in a synchronized or thread-safe context.
Immutable types cannot be shared because they're already thread-safe by nature.
You cannot change a shared type directly. You must borrow it using the := operator.
var int:shared foo = 100;
fn cannotChangeFoo()
{
foo++; // Error: foo is shared and must be in a synchronized or thread-safe context.
}
fn canChangeFoo()
{
sync
{
var int borrowedFoo := foo; // Borrow ownership
borrowedFoo++;
foo = borrowedFoo; // Return ownership
}
}