moritz has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to use Coro to implement a Perl 6-like gather { ... take() } construct.

I ran into the problem that I might have many coroutines, and I want to run one specific of them, and after then return to the main coro.

use strict; use warnings; use Coro; my $ca = async { print "coro a\n"; cede; } my $cb = async { print "coro b\n"; cede; } print "In main\n"; cede; print "Back in main\n"; __END__ In main coro b coro a Back in main

Here in main I call cede, but I don't seem to have control which coro should be next, and which one should be called after that.

How can I influence the call order?

I tried to fiddle a bit with priorities, setting the one that I want to call to highest, and main to second highest priority, but it didn't work for me:

# coro definitions of $ca and $cb as above my $main = Coro::current; $main->prio(2); $ca->prio(3); cede; print "In main\n"; __END__ In main

As you can see, no other coro is called ;( Can I somehow tweak the priority system to achieve my goal? or is there an even better way?

Update: I know solved the Problem with Coro::Channel. The result is now on CPAN: Perl6::GatherTake.

Replies are listed 'Best First'.
Re: Coro: running a specific coroutine
by Corion (Patriarch) on Apr 03, 2008 at 14:44 UTC

    I don't really understand what you want to do. If you want a specific coroutine to run to completion, use $coro->join(). If you want to run any coroutine until no more work is to be done, use Coro::schedule. If you want to start "any coroutine other than me", use cede_notself. In any case, you need to ->join all coroutines that you have spawned at some time earlier in the program, because once the main coroutine ends, no other coroutines will be called anymore.

    If you can describe more closely why and how you want to influence the call order, maybe we can find some way. The easiest solution would be if cede took an optional parameter giving the next coroutine to run, but I'm not sure there is a use case for that.

    Update: I think the (undocumented) $coro->transfer( $target ) method is what you want to transfer control to another, specified coroutine.

      I want to call a specific coro (let's say the one in $ca, and when $ca calls cede, it should return to my original ($main) coro.

      And I want that to happen several times, so throwing an exception instead of calling cede in $ca is not an option.

      Update: we talked a lot on the CB, and it seems that Coro::Channel will help me a great deal. I'll have to experiment with it a bit before I can tell if it actually works.

      ->transfer is documented in Coro::State. And you can do what you want like this:
      my $empty = new Coro::State; my $other; $other = new Coro::State sub { print "hi\n"; $other->transfer ($empty); }; $empty->transfer ($other);
      see also the t/00* test script which does this.