class Lock::Async

Low-level non-blocking non-re-entrant mutual exclusion lock

class Lock::Async {}

An asynchronous lock provides a non-blocking non-re-entrant mechanism for mutual exclusion. The lock method returns a Promise, which will already be kept if nothing was holding the lock already, so execution can proceed immediately. For performance reasons, in this case it returns a singleton Promise instance. Otherwise, a Promise in planned state will be returned, and kept once the lock has been unlocked by its current holder. The lock and unlock do not need to take place on the same thread; that's why it's not re-entrant.

High-level Perl 6 code should avoid the direct usage of locks, because they are not composable. Instead, high-level constructs such as Channel and Supply should be used whenever possible.

Methods

method protect

Defined as:

method protect(Lock::Async:D: &code)

Runs &code and makes sure it is only run in one thread at once.

Note that the Lock::Async itself needs to be created outside the portion of the code that gets threaded and it needs to protect. In the first example below, Lock::Async is first created and assigned to $lock, which is then used inside the Promises to protect the sensitive code. In the second example, a mistake is made, the Lock::Async is created right inside the Promise, so the code ends up with a bunch of separate locks, created in a bunch of threads, and thus they don't actually protect the code we want to protect.

# Right: $lock is instantiated outside the portion of the 
# code that will get threaded and be in need of protection 
my $lock = Lock::Async.new;
await ^20 .map: {
    start {
        $lock.protect: {
            print "Foo";
            sleep rand;
            say "Bar";
        }
    }
}
 
# !!! WRONG !!! Lock::Async is created inside threaded area! 
await ^20 .map: {
    start {
        Lock::Async.new.protect: {
            print "Foo"sleep randsay "Bar";
        }
    }
}

method lock

Defined as:

method lock(Lock::Async:D: --> Promise:D)

Acquires the lock, does not wait to acquire the lock. Returns a Promise that will be kept whenever the lock is acquired.

my $l = Lock::Async.new;
$l.lock;

method unlock

Defined as:

method unlock(Lock::Async:D: --> Nil)

Releases the lock, blocking until all Promised of all holders of the lock have been kept.

my $l = Lock::Async.new;
$l.lock;
$l.unlock;