Low-level non-blocking non-re-entrant mutual exclusion lock
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.
method protect(Lock::Async: )
&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 protectionmy = Lock::Async.new;await ^20 .map:# !!! WRONG !!! Lock::Async is instantiated inside threaded area!await ^20 .map:
method lock(Lock::Async: --> Promise)
Acquires the lock, does not wait to acquire the lock. Returns a Promise that will be kept whenever the lock is acquired.
my = Lock::Async.new;.lock;
method unlock(Lock::Async: --> Nil)
Releases the lock, blocking until all Promised of all holders of the lock have been kept.
my = Lock::Async.new;.lock;.unlock;