Skip to content

Commit 24fe425

Browse files
committed
First stab at documenting Lock::Async
1 parent 3afac8f commit 24fe425

File tree

1 file changed

+91
-0
lines changed

1 file changed

+91
-0
lines changed

doc/Type/Lock/Async.pod6

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
=begin pod
2+
3+
=TITLE class Lock::Async
4+
5+
=SUBTITLE Low-level non-blocking non-reentrant mutual exclusion lock
6+
7+
class Lock::Async {}
8+
9+
An asynchronous lock provides a non-blocking non-reentrant mechanism for
10+
mutual exclusion. The lock method returns a Promise, which will already be
11+
Kept if nothing was holding the lock already, so execution can proceed
12+
immediately. For performance reasons, in this case it returns a singleton
13+
Promise instance. Otherwise, a Promise in planned state will be returned,
14+
and Kept once the lock has been unlocked by its current holder. The lock
15+
and unlock do not need to take place on the same thread; that's why it's not
16+
reentrant.
17+
18+
High-level Perl 6 code should avoid the direct usage of locks, because they
19+
are not composable. Instead, high-level constructs such as
20+
L<Channel|/type/Channel> and L<Supply|/type/Supply> should be used
21+
whenever possible.
22+
23+
=head1 Methods
24+
25+
=head2 method protect
26+
27+
Defined as:
28+
29+
method protect(Lock::Async:D: &code)
30+
31+
Runs C<&code> and makes sure it is only run in one thread at once.
32+
33+
Note that the L<Lock::Async> itself needs to be created outside the portion
34+
of the code that gets threaded and it needs to protect. In the first
35+
example below, L<Lock::Async> is first created and assigned to C<$lock>,
36+
which is then used I<inside> the L<Promises|/type/Promise> to protect
37+
the sensitive code. In the second example, a mistake is made, the
38+
C<Lock::Async> is created right inside the L<Promise>, so the code ends up
39+
with a bunch of separate locks, created in a bunch of threads, and
40+
thus they don't actually protect the code we want to protect.
41+
42+
# Right: $lock is instantiated outside the portion of the
43+
# code that will get threaded and be in need of protection
44+
my $lock = Lock::Async.new;
45+
await ^20 .map: {
46+
start {
47+
$lock.protect: {
48+
print "Foo";
49+
sleep rand;
50+
say "Bar";
51+
}
52+
}
53+
}
54+
55+
# !!! WRONG !!! Lock::Async is created inside threaded area!
56+
await ^20 .map: {
57+
start {
58+
Lock::Async.new.protect: {
59+
print "Foo"; sleep rand; say "Bar";
60+
}
61+
}
62+
}
63+
64+
=head2 method lock
65+
66+
Defined as:
67+
68+
method lock(Lock::Async:D: --> Promise:D)
69+
70+
Acquires the lock, does B<not> wait to acquire the lock. Returns a Promise
71+
that will be kept whenever the lock is acquired.
72+
73+
my $l = Lock::Async.new;
74+
$l.lock;
75+
76+
=head2 method unlock
77+
78+
Defined as:
79+
80+
method unlock(Lock::Async:D: --> Nil)
81+
82+
Releases the lock, blocking until all Promised of all holders of the lock have
83+
been Kept.
84+
85+
my $l = Lock::Async.new;
86+
$l.lock;
87+
$l.unlock;
88+
89+
=end pod
90+
91+
# vim: expandtab softtabstop=4 shiftwidth=4 ft=perl6

0 commit comments

Comments
 (0)