Perl6-Pugs
view release on metacpan or search on metacpan
docs/Perl6/Spec/Concurrency.pod view on Meta::CPAN
my $thr = async {
...do something...
END { }
};
Conc::Thread.this
Conc::Proc.this
Conc object # name is still up for grabs!
- numify to TIDs (as in pugs)
- stringify to something sensible (eg. "<Conc:tid=5>");
- enumerable with Conc.list
- Conc.yield (if this is to live but deprecated, maybe call it sleep(0)?)
- sleep() always respects other threads, thank you very much
- standard methods:
- .join # wait for invocant to finish (always item cxt)
- .die # throw exception in the invocant thread
- .alarm # set up alarms
- .alarms # query existing alarms
- .suspend # pause a thread; fail if already paused
- .resume # revive a thread; fail if already running
- .detach # survives parent thread demise (promoted to process)
# process-local changes no longer affects parent
# tentatively, the control methods still applies to it
# including wait (which will always return undef)
# also needs to discard any atomicity context
- attributes:
- .started # time
- .finished # time
- .waiting # suspened (not diff from block on wakeup signal)
# waiting on a handle, a condition, a lock, et cetera
# otherwise returns false for running threads
# if it's finished then it's undef(?)
- .current_continuation
# the CC currently running in that thread
- "is throttled" trait
method throttled::trait_auxillary:<is> ($limit=1, :$key=gensym()) {
# "is throttled" limits max connection to this Code object
# the throttling is shared among closures with the same key
# the limit may differ on closures with the same key.
# if the counter with the "key" equals or exceeds a closure's limit,
# the closure can't be entered until it's released
# (this can be trivially implmented using atomic+retry)
}
class Foo {
method a is throttled(:limit(3) :key<blah>) { ... }
method b is throttled(:limit(2) :key<blah>) { ... }
}
my Foo $f .= new;
async { $f.a }
async { $f.b }
- Thread::Status
- IO objects and containers gets concurrency love!
- $obj.wake_on_readable
- $obj.wake_on_writable
- $obj.wake_on_either_readable_or_writable_or_passed_time(3); # fixme fixme
- $obj.wake_on:{.readable} # busy wait, probably
my @a is Array::Chan = 1..Inf;
async { @a.push(1) };
async { @a.blocking_shift({ ... }) };
async { @a.unshift({ ... }) };
Communication abstractions
- shared, transactional variables by default
# program will wait for _all_ threads
# unjoined threads will be joined at the beginning of the END block batch
# of the parent thread that spawned them
### INTERFACE BARRIER ###
module Blah;
{
is atomic; # retry/orelse/whatever other rollback stuff
# limitation: no external IO (without lethal warnings anyway)
# can't do anything irreversible
is critical; # free to do anything irreversible
# means "don't interrupt me"
# in system with critical section, no interrupts from
# other threads will happen during execution
# you can't suspend me
my $boo is export;
$boo = 1;
# We decree that this part forms the static interface
# it's run once during initial compilation under the
# Separate Compilation doctrine and the syms sealed off
# to form part fo bytecode syms headers
%CALLER::<&blah> = { 1 }; # work - adds to export set
die "Eureka!" if %CALLER::<$sym>; # never dies
# BEGIN { $boo = time };
sub IMPORT {
# VERY DYNAMIC!
our $i = time;
%CALLER::<&blah> = { 1 }; # work - adds to export set
die "Eureka!" if %CALLER::<$sym>; # probes interactively
}
}
### INTERFACE BARRIER ###
my $sym;
threads.new({
use Blah;
BEGIN { require(Blah).import }
my $boo; BEGIN { eval slurp<Blah.pm>; $boo := $Blah::boo };
...
});
=head2 Signals
( run in 2.124 seconds using v1.01-cache-2.11-cpan-5c0b1e786e0 )