Skip to content

Commit a91940a

Browse files
committed
More promises
1 parent 76c3921 commit a91940a

File tree

1 file changed

+85
-5
lines changed

1 file changed

+85
-5
lines changed

lib/Language/concurrency.pod

Lines changed: 85 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,10 @@ or reactive programming - that is an event or change in some part of a
1111
program may lead to an event or change in some other part of the program
1212
asynchronously to the program flow. )
1313
14-
The aim of the Perl concurrency design is to provide a consistent interface
15-
regardless of how a virtual may machine may implement it for a particular
16-
operating system, through layers of facilities as described below.
14+
The aim of the Perl concurrency design is to provide a consistent
15+
interface regardless of how a virtual machine may implement it for a
16+
particular operating system, through layers of facilities as described
17+
below.
1718
1819
=begin comment
1920
@@ -34,7 +35,8 @@ The lowest level interface for concurrency is provided by L<Thread>. A
3435
thread can be thought of as a piece of code that may eventually be run
3536
on a processor, the arrangement for which is made almost entirely by the
3637
virtual machine and/or operating system. Threads should be considered,
37-
for all intents, largely un-managed and should be avoided in user code.
38+
for all intents, largely un-managed and their direct use should be
39+
avoided in user code.
3840
3941
A thread can either be created and then actually run later:
4042
@@ -153,7 +155,85 @@ fails.) C<keep> changes the status of the promise to C<Kept> setting
153155
the result to the positional argument. C<result> blocks the current
154156
thread of execution until the promise is kept or broken, if it was kept
155157
then it will return the result (that is the value passed to C<keep>, )
156-
or it will throw an exception based on the value passed to C<break>.
158+
or it will throw an exception based on the value passed to C<break>. The
159+
latter behaviour is illustrated with:
160+
161+
my $promise1 = Promise.new();
162+
my $promise2 = $promise1.then(-> $v { say "Handled but : "; say $v.result});
163+
$promise1.break("First Result");
164+
try $promise2.result;
165+
say $promise2.cause;
166+
167+
Here the C<break> will cause the code block of the C<then> to throw an
168+
exception when it calls the C<result> method on the original promise
169+
that was passed as an argument which will subsequently cause the second
170+
promise to be broken, raising an exception in turn when its result
171+
is taken. The actual L<Exception> object will then be available from
172+
C<cause>. If the promise had not been broken C<cause> would raise a
173+
L<X::Promise::CauseOnlyValidOnBroken> exception.
174+
175+
A L<Promise> can also be scheduled to be automatically kept at a future time:
176+
177+
my $promise1 = Promise.in(5);
178+
my $promise2 = $promise1.then(-> $v { say $v.status; 'Second Result' });
179+
say $promise2.result;
180+
181+
The method C<in> creates a new promise and schedules a new task to call
182+
C<keep> on it no earlier than the supplied number of seconds, returning
183+
the new L<Promise> object. This is almost directly equivalent to calling
184+
C<Scheduler.cue> with a code block that will C<keep> the returned promise.
185+
186+
Possibly the most frequent requirement would be to schedule some code to
187+
be executed as soon as possible and obtain a promise that will be kept
188+
(or broken) when the code completes (or throws an exception,) this is
189+
performed by the method C<start> :
190+
191+
my $promise = Promise.start({ my $i = 0; for 1 .. 10 { $i += $_ }; $i});
192+
say $promise.result;
193+
194+
Here the C<result> of the promise returned is the value returned from
195+
the code. Similarly if the code fails (and the promise is thus broken,)
196+
then C<cause> will be the L<Exception> object that was thrown:
197+
198+
my $promise = Promise.start({ die "Broken Promise" });
199+
try $promise.result;
200+
say $promise.cause;
201+
202+
This is considered to be such a commonly required pattern that it is
203+
provided as subroutines:
204+
205+
my $result = await start {
206+
my $i = 0;
207+
for 1 .. 10 {
208+
$i += $_
209+
}
210+
$i
211+
}
212+
say $result;
213+
214+
C<await> is almost equivalent to calling C<result> on the promise object
215+
returned by C<start> but it will also take a list of promises and return
216+
the result of each:
217+
218+
my $result = await start({
219+
my $i = 0;
220+
for 1 .. 10 {
221+
$i += $_
222+
}
223+
$i
224+
}),
225+
start({
226+
my $i = 0;
227+
for 1 .. 10 {
228+
$i -= $_
229+
}
230+
$i
231+
});
232+
say $result;
233+
234+
235+
236+
157237
158238
159239

0 commit comments

Comments
 (0)