Last active
December 21, 2015 00:19
-
-
Save tadzik/6219412 to your computer and use it in GitHub Desktop.
Proposal for new select()
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# modelled after Go's select statement | |
# if something from selectors is ready, run it | |
# if more than one is ready, pick one at random | |
# if nothing is ready and there's a default, run the default | |
# otherwise, block on the non-ready tasks | |
# | |
# it'd be so much more elegant if we had tail recursion :] | |
use Test; | |
sub select(*@selectors, :$default) { | |
multi is-ready(Promise $p) { | |
if $p.has_result { | |
return (True, $p) | |
} | |
return (False, False) | |
} | |
multi is-ready(Channel $c) { | |
my $selected = $c.poll; | |
unless $selected === Nil { | |
return (True, $selected) | |
} | |
return (False, False) | |
} | |
multi is-ready(Any $c) { | |
die "Cannot use select on a " ~ .^name; | |
} | |
loop { | |
my @ready; | |
my @waiting; | |
for @selectors -> $s { | |
die "select expects to be passed a list of pairs" unless $s ~~ Pair; | |
my $arg = is-ready($s.key); | |
if $arg[0] { | |
@ready.push: $s.value => $arg[1] | |
} else { | |
@waiting.push: $s | |
} | |
} | |
if @ready { | |
my $choice = @ready.pick; | |
return $choice.key.($choice.value) | |
} elsif $default { | |
return $default.() | |
} | |
} | |
} | |
my $p1 = Promise.new; | |
my $p2 = Promise.new; | |
$p1.keep(1); | |
select( | |
$p1 => sub (Mu $) { ok 'finished promise is chosen' }, | |
$p2 => sub (Mu $) { nok 'running promise should not be chosen' }, | |
); | |
select( | |
$p2 => sub (Mu $) { nok 'running promise should not be chosen' }, | |
default => sub { ok 'default is chosen' }, | |
); | |
select( | |
$p1 => sub (Mu $) { ok 'finished promise wins over default' }, | |
default => sub { nok 'default is not chosen' }, | |
); | |
dies_ok { select(5 => 6); } | |
done; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment