Perl6-Pugs

 view release on metacpan or  search on metacpan

docs/Perl6/Spec/Concurrency.pod  view on Meta::CPAN

It returns a proxy alarm object that you can do interesting things with.

    multi Alarm *alarm (Num $seconds = $CALLER::_, &do = {die Sig::ALARM}, :$repeat = 1)
    multi Alarm *alarm (Date $date, &do = {die Sig::ALARM}, :$repeat = 1)

Perl 6's C<alarm> has three additional features over traditional alarms:

=head3 Multiple and Lexical Alarms

One can set up multiple alarms using repeated alarm calls:

    {
        my $a1 = alarm(2);
        my $a2 = alarm(2);
        sleep 10;
        CATCH {
            is critical; # if you don't want $a2 to be raised inside this
            when Sig::ALARM { ... } 
        }
    }

To stop an alarm, call C<$alarm.stop>.  The C<alarms> method for Conc objects
(including process and threads) returns a list of alarms currently scheduled
for that concurrent context.

When an alarm object is garbage collected, the alarm is stopped automatically.
Under void context, the implicit alarm object can only be stopped by querying
C<.alarms> on the current process.

We are not sure what C<alarm(0)> would mean.  Probably a deprecation warning?

=head3 Repeated Alarms

If you request a repeated alarm using the C<repeated> named argument, it will
attempt to fire off the alarm that many times.  However, the alarm will be
supressed when inside a C<CATCH> block that's already handling the exception
raised by I<same> alarm.

To repeat 0 times is to not fire off any alarms at all.  To repeat +Inf times
is to repeat over and over again.

=head3 Callbacks in Alarms

You can arrange a callback (like JavaScript's setTimeOut) in C<alarm>, which
will then be invoked with the then-current code as caller.

If you set up such a callback to another Conc object, what happens is just like
when you called C<.die> on behalf of that object -- namely, the callback
closure, along with anything it referenced, is shared to the target Conc
context.

Unlike in Perl 5's ithreads where you cannot share anything after the fact,
this allows passing shared objects in an C<ad-hoc> fashion across concurrent
parts of the program.  Under the default (multiplexing) concurrency model, this
is basically a no-op.

=head2 Continuations

=head3 Coroutines

## braindump of coro meeting by Liz and Autri, more to follow

- Coros are _like_ processes

coro dbl { yield $_ * 2; yield $_; return };
my @x = 1..10;
my %y = map &dbl, @x;
# 2 => 2, 6 => 4, 10 => 6, ...

coro perm (@x) {
    @x.splice(rand(@x),1).yield while @x;
}

my &p1 := &perm.start(1..10);
my &p2 := &perm.start(1..20);

p1(); p1();
p2(); p2();

coro foo { yield 42 };

(1..10).pick;

coro foo ($x) {
    yield $x;
    yield $x+2;
    cleanup();
    while (2) {
        while (1) {
            &?SUB.kill; # seppuku
        }
    }
} # implicit falloff return + return() means startover without yielding
  # return() means yielding and restart + no implicit falloff (I LIKE THIS)

&foo.finished; # true on return() and false on midway yield()

foo(4); # and that's all she wrote

coro foo ($x) {
    yield $x;
    # this point with $x bound to 10
    yield $x+1;
    return 5;
    ... # this is never reached, I think we all agree
}

# If you don't want your variables to get rebound, use "is copy":
coro foo ($x is copy) {...}
# which is sugar for
coro foo ($x) {
  {
    my $x := $OUTER::x;
    ...;
    # Further calls of &foo rebound $OUTER::x, not $x.
  }
}

sub foo {
    return undef if rand;
    ...
}

use overload {
    '&{}' => sub { ... }
}

class Coro is Conc::Multiplex does Code {
    method postcircumfix:<( )> {
        # start the thread, block stuff (we are in the caller's context)
    }
}

class Hash is extended {
    method postcircumfix:<( )> (&self: *@_) {
        &self = self.start(@_);
    }
    method start {
        # remember self
        # upon return() or normal falloff, restore self
    }
}

%*ENV(123);

&foo_continued := &foo.start(10);
&foo.start(20);

foo(10);    # returns 10

foo();      # be "insufficient param" error or just return 11?
foo(20);    # returns 21

# continuation coros
multi foo () { ...no rebinding... }
multi foo ($x) { ...rebinding... }

&foo.kill;


my $first_ret = zoro( type => <even> );
&zoro.variant(:type<even>).kill;
&zoro.variant(type => 'even').kill;

zoro( type => <odd> );

zoro( even => 1 );
zoro( odd => 1 );

multi coro zoro ($type where 'even') {}
multi coro zoro ($type where 'odd') {}

multi coro zoro ($even is named) {}
multi coro zoro ($odd is named) {}


# iblech's thoughts:
# Coroutine parameters should never be rebound. Instead, yield(...)s return
# value is an Arglist object containing the new arguments:
coro bar ($a, $b) {
    ...;
    my $new_set_of_args = yield(...);
    my $sum_of_old_a_and_new_a = $a + $new_set_of_args<$a>;
    ...;
}
bar(42, 23);  # $a is 42, $b is 23
bar(17, 19);  # $a still 42, $b still 19,
              # $new_set_of_args is \(a => 17, b => 19)

=head2 Junctive Autothreading and Hyper Operations

Live in userland for the time being.

=head2 Interprocess Communication

=head2 I/O Considerations

=head3 File Descriptors

=head3 Sockets

=cut



( run in 0.483 second using v1.01-cache-2.11-cpan-e93a5daba3e )