@@ -379,45 +379,83 @@ result.
379
379
my ($a, $b) = await $p1, $p2;
380
380
381
381
This simply calls C<result> on each of the C<Promise>s, so any exception will
382
- be thrown. There is also a C<winner> statement [keywords still negotiable]:
382
+ be thrown.
383
383
384
- winner * {
385
- done $p1 { say "First promise got a value" }
386
- done $p2 { say "Second promise got a value" }
384
+ There is also an C<outcome> statement [keywords still negotiable]. In its
385
+ simplest form it just takes a list of C<Promise>s and C<Channel>s and returns
386
+ a lazy list of all the values returned by all Promises and Channels specified:
387
+
388
+ my @values = outcome @p, @c;
389
+
390
+ If a C<Promise> is broken, then the value returned is a C<Failure> object
391
+ with the C<.excuse>. Please note that this simple form will block until all
392
+ values have been found. You can also put this simple form in a loop for
393
+ processing:
394
+
395
+ for outcome( @p, @c ) -> $value {
396
+ # process $value
387
397
}
388
398
389
- That will invoke the closure associated with the first promise that
390
- produces a result, either kept or broken.
399
+ in which case values will be processed as they become available.
391
400
392
- It's possible to add a timer using the keyword C<wait> followed
393
- by the number of seconds to wait (which may be fractional). As a
394
- degenerate case, in order to avoid blocking at all you may use a
395
- C<wait 0>. The timeout is always checked last, to guarantee that
396
- the other entries are all tried at least once before timing out.
401
+ For more control, one can also specify a closure, in which there is more
402
+ control over how a C<Promise> and / or a C<Channel> are being processed.
403
+ In such a case, the returned lazy list with values is generally not needed:
397
404
398
- my $gotone = winner * {
399
- done $p1 { say "First promise got a value"; $p1 }
400
- done $p2 { say "Second promise got a value "; $p2 }
401
- wait 0 { say "Not done yet"; Nil }
405
+ my @values;
406
+ outcome {
407
+ whenever $p1 { say "p1 fired "; @values.push: $_ }
408
+ whenever @p,@c { @values.push: $_ }
402
409
}
403
410
404
- The construct as a whole returns the result of whichever block was selected.
411
+ Please note that for C<Promise>s, the C<whenever> will only be called once.
412
+ For C<Channel>s, it will be called as soon as a value is present on the
413
+ Channel until the Channel is C<.closed>.
414
+
415
+ There is also a C<done> keyword that can be used to specify code to be run
416
+ when a C<Channel> has closed:
405
417
406
- It's also possible to process a variadic list of promises together,
407
- using generic code that works over some set of the promises (use C<*>
408
- to represent any of them). The index and promise are passed to the
409
- code as named arguments C<$:v> and <$:k> (possibly via priming if
410
- the code is instantiated ahead of time).
418
+ outcome {
419
+ ...
420
+ done @c { say "Channel $_ has closed" }
421
+ }
422
+
423
+ It's possible to add a timer using the keyword C<wait> followed by the
424
+ number of seconds to wait (which may be fractional) since the last value
425
+ found by a C<whenever> has been seen. The timeout is always checked last,
426
+ to guarantee that the other entries are all tried at least once before
427
+ timing out.
411
428
412
- winner * {
413
- done @promises { say "Promise $:k was kept, result was: ", $:v.result }
429
+ outcome {
430
+ ...
431
+ wait 5 { say "Not done yet" }
414
432
}
415
433
416
- In this case C<$:k> returns the index of the promise, base 0.
417
- Likewise C<$:v> returns the promise object itself. Conjecture: the result
418
- should be bound to C<$_> to make it work more like channels below.
419
434
420
- [Conjecture: we should allow different cases for success or failure.]
435
+ As a degenerate case, in order to avoid blocking at all you may use a
436
+ C<wait 0>. Together with C<last>, this allows one to exit the C<outcome>
437
+ prematurely whenever there is nothing happening:
438
+
439
+ loop {
440
+ outcome {
441
+ ...
442
+ wait 0 { say "Giving up for now"; last }
443
+ }
444
+ # do other stuff
445
+ }
446
+
447
+ Please note that you will need to C<.redeem> any C<Promise> that has been
448
+ kept or broken, to prevent it from being seen again in the next loop
449
+ iteration. Something like this:
450
+
451
+ my @values;
452
+ loop {
453
+ outcome {
454
+ whenever @p { $:promise.redeem; @values.push: $_ }
455
+ wait 0 { say "Giving up for now"; last }
456
+ }
457
+ # do other stuff
458
+ }
421
459
422
460
=head1 Channels
423
461
@@ -453,22 +491,14 @@ calls to a channel return the same promise, not a new one.
453
491
While C<receive> blocks until it can read, C<poll> takes a message from the
454
492
channel if one is there or immediately returns C<Nil> if nothing is there.
455
493
456
- The C<winner> construct also works on channels, and will try to receive a value
457
- from the first C<Channel> that has one available. It also automatically checks
458
- the C<.done> promise corresponding to the channel, so it can also be used in order
459
- to write a loop to receive from a channel until it is closed:
494
+ The C<outcome> construct also works on channels, and will try to receive
495
+ values from the any C<Channel> that has value(s) available until they are
496
+ all closed.
460
497
461
- gather loop {
462
- winner $channel {
463
- more * { take $_ }
464
- done * { last }
465
- }
498
+ outcome {
499
+ whenever $channel { take $_ }
466
500
}
467
501
468
- This works because C<more> only ever works on channels, while C<done>
469
- only ever works on promises, so it knows to check the promise of
470
- channel C<$c> rather than C<$c> itself.
471
-
472
502
This is such a common pattern that we make a channel in list context behave
473
503
that way:
474
504
0 commit comments