Skip to content

Commit

Permalink
Introduce .cue(:times(42)) and .cue(:stop($var))
Browse files Browse the repository at this point in the history
  • Loading branch information
lizmat committed Nov 10, 2013
1 parent 71fd6d3 commit 98c34a7
Showing 1 changed file with 29 additions and 11 deletions.
40 changes: 29 additions & 11 deletions S17-concurrency.pod
Expand Up @@ -172,15 +172,6 @@ or at a given absolute time, specified as an C<Instant>:

$*SCHEDULER.cue: at=>$instant, { say "10s later" }

Use C<:every> to schedule an operation to run at a fixed interval, possibly with a
delay before the first scheduling.

# Every second, from now
$*SCHEDULER.cue: :every(1), { say "Oh wow, a kangaroo!" }

# Every 0.5s, but don't start for 2s.
$*SCHEDULER.cue({ say "Kenya believe it?" }, :every(0.5), :in(2));

If a scheduled item dies, the scheduler will catch this exception and pass it
to a C<handle_uncaught> method, a default implementation of which is provided
by the C<Scheduler> role. This by default will report the exception and cause
Expand All @@ -197,6 +188,33 @@ code object to be invoked with the thrown exception if it dies:
{ upload_progress($stuff) },
catch => -> $ex { warn "Could not upload latest progress" }

Use C<:every> to schedule a task to run at a fixed interval, possibly
with a delay before the first scheduling.

# Every second, from now
$*SCHEDULER.cue: :every(1), { say "Oh wow, a kangaroo!" };

# Every 0.5s, but don't start for 2s.
$*SCHEDULER.cue: { say "Kenya believe it?" }, :every(0.5), :in(2);

Since this will cause the given to be executed for the given interval ad
infinitum, there are two ways to make sure the scheduling of the task is
halted at a future time. The first is provided by specifying the C<:times>
parameter in the .cue:

# Every second, from now, but only 42 times
$*SCHEDULER.cue: :every(1), :times(42), { say "Oh wow, a kangaroo!" };

The second is by specifying a variable that will be checked at the end of
each interval. The task will be stopped as soon as it has a True value.
You can do this with the C<:stop> parameter.

# Every second, from now, until stopped
my $stop;
$*SCHEDULER.cue: :every(1), :$stop, { say "Oh wow, a kangaroo!" };
sleep 10;
$stop = True; # task stopped after 10 seconds

Schedulers also provide counts of the number of operations in various states:

say $*SCHEDULER.loads;
Expand All @@ -206,8 +224,8 @@ delays, the number of cues that are runnable but not yet assigned to a thread,
and the number of cues that are now assigned to a thread (and presumably running).
[Conjecture: perhaps these should be separate methods.]

Schedulers may optionally provide further introspection in order to support tools
such as debuggers.
Schedulers may optionally provide further introspection in order to support
tools such as debuggers.

There is also a C<CurrentThreadScheduler>, which always schedules things on
the current thread. It provides the same methods, just no concurrency, and
Expand Down

3 comments on commit 98c34a7

@anjohnson
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not terribly p6-literate even though I've been following development for years, but shouldn't the example of using :stop actually name the parameter, like this?

$*SCHEDULER.cue: :every(1), :stop($stop), { say "Oh wow, a kangaroo!" };

@Timbus
Copy link

@Timbus Timbus commented on 98c34a7 Nov 17, 2013

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No it's prefectly fine. ref http://perlcabal.org/syn/S06.html#Named_arguments
"Variables with a : prefix in rvalue context autogenerate pairs..."

@anjohnson
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wow, cool -- thanks!

Please sign in to comment.