enum Event <Exit Enter Quit Last Last-Phaser>;
role SupplyInspector {
method event(
Event:D :$event!,
Str:D :$spec!,
:$value, # only present in Enter
Numeric :$elapsed, # not present in Enter
Exception :$exception, # only present in Quit
Str :$phaser-spec, # only present in Quit and Last-Phaser
Bool :$has-phaser, # only present in Quit, Last and Last-Phaser
) { ... }
}
class SupplyInspector::Print does SupplyInspector {
method event(Event:D :$event!, Str:D :$spec!, :$value,
Numeric :$elapsed, Exception :$exception,
Str :$phaser-spec, Bool :$has-phaser) {
my $ts = (now - INIT now).round(0.001) ~ 's';
my sub c(Int $c, Str $t) { "\e[{$c}m{$t}\e[0m" }
my $tag = c(31 + $event, $event.uc);
say qq:to/END/.indent(4);
[$ts]{
$has-phaser eqv False ?? c(35, " NO PHASER") !! ""
} $tag {$spec}{
$value // ""
}{
$elapsed ?? " ({$elapsed.round(0.001)}s)" !! ""
}{
$exception ?? "\n{c(38, "Exception")}:\n{$exception.gist.indent(4)}" !! ""
}{
$phaser-spec ?? " [phaser: $phaser-spec]" !! ""
}
END
}
}
sub INSPECT-SUPPLY(SupplyInspector :$inspector = SupplyInspector::Print.new) {
use nqp;
my &OLD := nqp::getlexdyn('&*ADD-WHENEVER');
my &NEW := sub (Supply $s, &block) {
my $spec = "{&block.file}:{&block.line}";
my $q = &block.phasers('QUIT')[0];
my $qspec = $q.DEFINITE ?? "{$q.file}:{$q.line}" !! Str;
my $has-q = $q.DEFINITE;
my @lasts = &block.phasers('LAST').map: -> &l {
("{&l.file}:{&l.line}", &l)
}
OLD($s, -> $value {
my $enter = now;
$inspector.event(:event(Enter), :$spec, :$value);
LEAVE $inspector.event(:event(Exit), :$spec,
:elapsed(now - $enter));
QUIT {
default {
my $enter = now;
$q($_) if $has-q;
$inspector.event(
:event(Quit), :$spec,
:exception($_),
:phaser-spec($qspec),
:has-phaser($has-q),
:elapsed(now - $enter),
);
}
}
&block($value);
LAST {
my $enter = now;
for @lasts -> ($lspec, $lphaser) {
my $enter = now;
$lphaser();
$inspector.event(
:event(Last-Phaser), :$spec,
:phaser-spec($lspec),
:has-phaser(True),
:elapsed(now - $enter),
);
}
$inspector.event(
:event(Last), :$spec,
:elapsed(now - $enter),
:has-phaser(@lasts.so),
);
}
});
}
nqp::bindlexdyn('&*ADD-WHENEVER', &NEW);
}
sub foo($n) {
supply {
INSPECT-SUPPLY;
whenever Promise.in(1) { whenever ^3 { "$n: $_".say; sleep .2; } } }
};
await supply {
INSPECT-SUPPLY;
for ^3 -> $n {
whenever foo($n) { LAST { say "end" } }
}
} # suddenly multithreaded