On Sat Dec 05 11:13:54 2015, b...@abrij.org wrote:
> 
> 16:18   skids   I think the Supply work may have made
> $fh.watch.Promise not fire anymore.
> 16:20           watch.tap still works.
> 16:21   jnthn   The semantics of Supply.Promise changed
> 16:21           You'll need $fh.watch.head(1).Promise to get the
> original ones
> 16:21   skids   Ah that would explain it.  jnthn++
> 16:22           Hrm that doesn't seem to do it though.
>                 2 more elements. Show/hide.
> 16:34   jnthn   Hm, head doesn't seem to be filing the "done"
> 
> These work:
> 
> $ perl6 -e 'my $f = Supplier.new; my $s = $f.head(1).Supply; my $t =
> $s.tap(-> $ { 42.say }, done => {43.say} ); start { for 0..3 {
> $f.emit(42) }; $f.done(); }; await $s.Promise; 44.say; '
> 42
> 43
> 44
> 
> $ perl6 -e 'my $f = Supplier.new; my $s = $f.head(1).Supply; my $t =
> $s.tap(-> $ { 42.say }, done => {43.say} ); start { for 0..3 {
> $f.emit(42) }; }; await $s.Promise; 44.say; '
> 42
> 43
> 44
> 
> 
> This neither sends a done nor fulfills a .Promise (input echoed into
> file from another terminal):
> 
> $ perl6 -e 'my $fh = open("/tmp/foo.txt", :create); my $s =
> $fh.watch.head(1); my $t = $s.tap(-> $ { 42.say }, done => {43.say} );
> await $s.Promise; 44.say'
> 42
> ^C
> 
This works reliably now, and so could do with a test. Probably thanks to one of 
the many Supply fixes over the last months.

> ...and when the .head is off a Supply instead of a Supplier, a done
> from the original Supply propagates but the Promise never unhooks:
> 
> $ perl6 -e 'my $f = Supplier.new; my $s = $f.Supply.head(1); my $t =
> $s.tap(-> $ { 42.say }, done => {43.say} ); start { for 0..3 {
> $f.emit(42) }; $f.done(); }; await $s.Promise; 44.say; '
> 42
> 43
> ^C
> 
> $ perl6 -e 'my $f = Supplier.new; my $s = $f.Supply.head(1); my $t =
> $s.tap(-> $ { 42.say }, done => {43.say} ); start { for 0..3 {
> $f.emit(42) }; }; await $s.Promise; 44.say; '
> 42
> ^C

This code is vulnerable to a race condition, thus it sometimes works, sometimes 
not. If you add a `sleep 1` before the `await` then it reliably hangs. The 
reason is that a Supplier is a live supply; if you miss the events (emit/done) 
then they're gone for good. (Note that `.Promise` taps the supply separately 
from the `.tap` that is already taking place.) For this to reliably work, the 
`Promise` should be obtained prior to setting off the `start` block. This works 
reliably, every time:

my $f = Supplier.new;
my $s = $f.Supply.head(1);
my $t = $s.tap(-> $ { 42.say }, done => {43.say} );
my $p = $s.Promise;
start {
    for 0..3 {
        $f.emit(42)
    };
    $f.done();
}
await $p;
44.say;

Tagging testneeded for the part that deserves a test.

/jnthn

Reply via email to