Skip to content

Commit c243ac1

Browse files
committed
Add Promise.vow
1 parent b005b2c commit c243ac1

File tree

1 file changed

+54
-26
lines changed

1 file changed

+54
-26
lines changed

lib/Language/concurrency.pod

Lines changed: 54 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@ user code should, where possible, avoid the lower level concurrency APIs
3535
=head2 Promises
3636
3737
A L<Promise|/type/Promise> (also called I<future> in other programming
38-
environments) encapsulates the result of a computation
39-
that may not have completed or even started at the time the
40-
promise is obtained. It provides much of the functionality that user code
41-
needs to operate in a concurrent or asynchronous manner.
38+
environments) encapsulates the result of a computation that may not
39+
have completed or even started at the time the promise is obtained.
40+
It provides much of the functionality that user code needs to operate
41+
in a concurrent or asynchronous manner.
4242
4343
=begin code
4444
my $p1 = Promise.new;
@@ -63,16 +63,16 @@ chaining:
6363
$promise1.keep("First Result");
6464
say $promise2.result; # First Result \n Second Result
6565
66-
Here the L<then|/type/Promise#method_then> schedules code to be executed
67-
when the first L<Promise> is kept or broken, itself returning a new
68-
L<Promise> which will be kept
69-
with the result of the code when it is executed (or broken if the code
70-
fails.) C<keep> changes the status of the promise to C<Kept> setting
71-
the result to the positional argument. C<result> blocks the current
72-
thread of execution until the promise is kept or broken, if it was kept
73-
then it will return the result (that is the value passed to C<keep>, )
74-
or it will throw an exception based on the value passed to C<break>. The
75-
latter behaviour is illustrated with:
66+
Here the L<then|/type/Promise#method_then> schedules code to be
67+
executed when the first L<Promise> is kept or broken, itself returning
68+
a new L<Promise> which will be kept with the result of the code when
69+
it is executed (or broken if the code fails.) C<keep> changes the
70+
status of the promise to C<Kept> setting the result to the positional
71+
argument. C<result> blocks the current thread of execution until the
72+
promise is kept or broken, if it was kept then it will return the
73+
result (that is the value passed to C<keep>, ) or it will throw an
74+
exception based on the value passed to C<break>. The latter behaviour
75+
is illustrated with:
7676
7777
my $promise1 = Promise.new();
7878
my $promise2 = $promise1.then(-> $v { say "Handled but : "; say $v.result});
@@ -94,13 +94,14 @@ A L<Promise> can also be scheduled to be automatically kept at a future time:
9494
my $promise2 = $promise1.then(-> $v { say $v.status; 'Second Result' });
9595
say $promise2.result;
9696
97-
The L<method in|/type/Promise#method_in> creates a new promise and schedules a new task to call
98-
C<keep> on it no earlier than the supplied number of seconds, returning
99-
the new L<Promise> object.
97+
The L<method in|/type/Promise#method_in> creates a new promise and
98+
schedules a new task to call C<keep> on it no earlier than the supplied
99+
number of seconds, returning the new L<Promise> object.
100100
101101
A very frequent use of promises is to run a piece of code, and keep the
102102
promise once it returns successfully, or break it when the code dies.
103-
The L<start method|/type/Promise#method_start> provides a shortcut for that:
103+
The L<start method|/type/Promise#method_start> provides a shortcut
104+
for that:
104105
105106
my $promise = Promise.start(
106107
{ my $i = 0; for 1 .. 10 { $i += $_ }; $i}
@@ -179,6 +180,33 @@ when the completion or otherwise of the tasks is more important to the
179180
consumer than the actual results, or the results have been collected by
180181
other means.
181182
183+
If you are creating a promise that you intend to keep or break yourself
184+
then you probably don't want any code that might receive the promise to
185+
inadvertently (or otherwise,) keep or break the promise before you do.
186+
For this purpose there is the L<method vow|/type/Promise#method_vow>, which
187+
returns a L<Vow> object which becomes the only mechanism by the promise
188+
can be kept or broken. If an attempt to keep or break the Promise is made
189+
directly then the exception L<X::Promise::Vowed> will be thrown, as long
190+
as the vow object is kept private, the status of the promise is safe:
191+
192+
sub get_promise {
193+
my $promise = Promise.new;
194+
my $vow = $promise.vow;
195+
Promise.in(10).then({$vow.keep});
196+
$promise;
197+
}
198+
199+
my $promise = get_promise();
200+
201+
# Will throw an exception
202+
# "Access denied to keep/break this Promise; already vowed"
203+
$promise.keep;
204+
205+
The methods that return a promise that will be kept or broken
206+
automatically such as C<in> or C<start> will do this, so it is not
207+
necessary to do it for these.
208+
209+
182210
183211
=head2 Supplies
184212
@@ -212,18 +240,18 @@ interested in the events:
212240
$tap.close; # Will trigger the closing callback
213241
$supply.emit("Won't trigger the tap");
214242
215-
Calling C<close> on the L<Tap> object (or calling C<close> on the supply
216-
object with the tap object as an argument,) triggers the callback
243+
Calling C<close> on the L<Tap> object (or calling C<close> on the
244+
supply object with the tap object as an argument,) triggers the callback
217245
specified by C<closing> if present and stop further events being sent to
218246
the tap callback but otherwise leave the supply intact to receive further
219-
events. Calling C<done> on the supply object similarly calls the
220-
C<done> callback that may be specified for any taps, but does not prevent any
247+
events. Calling C<done> on the supply object similarly calls the C<done>
248+
callback that may be specified for any taps, but does not prevent any
221249
further events being emitted to the stream, or taps receiving them.
222250
223-
The method C<interval> returns a new supply which peridically
224-
emits a new event at the specified interval. The data that is emitted
225-
is an integer starting at 0 that is incremented for each event. The
226-
following code outputs 0 .. 5 :
251+
The method C<interval> returns a new supply which peridically emits
252+
a new event at the specified interval. The data that is emitted is an
253+
integer starting at 0 that is incremented for each event. The following
254+
code outputs 0 .. 5 :
227255
228256
my $supply = Supply.interval(2);
229257
$supply.tap(-> $v { say $v });

0 commit comments

Comments
 (0)