Skip to content

Instantly share code, notes, and snippets.

@tadzik
Last active December 21, 2015 00:19
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save tadzik/6219412 to your computer and use it in GitHub Desktop.
Save tadzik/6219412 to your computer and use it in GitHub Desktop.
Proposal for new select()
# 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