```{index} single: Coro::State ``` # Coro::State ```{pperl-module-badges} Coro::State ``` `Coro::State` - the engine under Coro: Perl-level threads ("coroutines") with their own call stacks, switched cooperatively. ```perl use Coro; # Three coroutines take turns: each cede lets the next ready one run. my @workers = map { my $id = $_; async { for my $step (1 .. 2) { print "worker $id, step $step\n"; cede; } return "worker $id done"; }; } 1 .. 3; print $_->join, "\n" for @workers; # wait for each, collect its result # A semaphore makes the others wait while one holds it. my $lock = Coro::Semaphore->new(1); my $t = async { my $g = $lock->guard; print "got the lock\n" }; { my $g = $lock->guard; cede; # $t runs, and blocks on the lock print "releasing, ", scalar($lock->waiters), " waiting\n"; } $t->join; # The engine underneath: switch between two states by hand. my ($main, $other); $other = Coro::State->new(sub { print "in other\n"; $other->transfer($main) }); $main = Coro::State->new; $main->transfer($other); print "back in main\n"; ``` prints `worker 1, step 1` to `worker 3, step 1`, then the three step 2 lines, the three `done` lines, `releasing, 1 waiting`, `got the lock`, `in other` and `back in main`. Most programs use `Coro` and never touch `Coro::State` directly. `Coro::State` is the machinery: a coroutine for a sub, and switching from one to another. Coro's scheduler, its coroutine objects, `Coro::Semaphore` and `Coro::Signal` are built on it, and their XS half lives here too. Each coroutine has its own `$_`, `@_`, `$@`, `$/`, `$1`..., `$^H` and `%^H`, die and warn hooks (`$Coro::State::DIEHOOK` and `WARNHOOK` are the defaults), default output handle, `local` values and lexicals. A coroutine that switches away from inside a sort block, a tie method, a `DESTROY` or any other callback keeps a C stack of its own until it gets back out; the size of those stacks is `Coro::State::cctx_stacksize`, in pointers (default 16384, which is 128 KiB). This is a native implementation of the XS half of Coro 6.57; its `Coro.pm` and every `Coro::*` module are used unchanged. `use Coro` exports `async`, `async_pool`, `cede`, `schedule`, `terminate`, `current`, `unblock_sub`, `rouse_cb` and `rouse_wait`; the `PRIO_*` constants and `nready` on request. `Coro::State` exports nothing. `Coro::State::BACKEND` names the stack-switch method: `asm` on x86-64, `sjlj` (setjmp/longjmp) elsewhere - what Coro's own build picks on Linux. ## Coroutines: the Coro functions - `async { ... } @args` creates a coroutine running the block with `@args`, puts it in the ready queue and returns its `Coro` object. Returning from the block ends it; an uncaught `die` ends the program, as in the main program. - `async_pool { ... } @args` is the same with a coroutine from a pool of reused ones: faster, runs the block in an `eval` (a `die` warns), and never terminates, so it is not to be joined. - `Coro->new(\&sub, @args)` creates a coroutine without readying it. - `cede` puts the current coroutine at the end of the ready queue and runs the next one of the same or higher priority; `Coro::cede_notself` cedes to any ready one, whatever its priority. - `schedule` runs the next ready coroutine without readying the current one: the way to block until something calls `->ready`. - `terminate @values` ends the current coroutine with those values. - `Coro::nready` is the number of coroutines in the ready queue. - `rouse_cb` returns a callback; `rouse_wait` blocks until that callback (or the one passed to it) has been called, and returns the arguments it was called with. They turn a callback API into a blocking call. - `Coro::on_enter BLOCK` and `Coro::on_leave BLOCK` run their block whenever the current coroutine is switched to or away from, while the enclosing scope lasts. The methods of a `Coro` object `$coro`: - `$coro->ready` queues it; false when it already was. `$coro->suspend` keeps the scheduler from running it until `$coro->resume`. - `$coro->join` waits for it to end and returns its values (the block's return value, or what `terminate` or `cancel` gave). - `$coro->cancel(@values)` ends it at once, from outside; `$coro->safe_cancel(@values)` ends it from inside, so its cleanup runs in its own context, and dies when it is not in a state where that can be done. `$coro->throw($exception)` makes it die with `$exception` when it next runs. - `$coro->on_destroy(\&cb)` calls `cb` with its values when it ends. - `$coro->schedule_to` and `$coro->cede_to` switch to it directly, bypassing the queue; `cede_to` readies the current coroutine first. - `$coro->prio($new)` and `$coro->nice($change)` set its priority (from `PRIO_MIN`, -4, to `PRIO_MAX`, 3; `nice` subtracts) and return the previous one. - `$coro->is_new`, `is_ready`, `is_running`, `is_suspended`, `is_zombie` (ended) and `is_destroyed` (the same) report its state. `Coro::Semaphore->new($count)` has `down` (wait until the count is positive, then take one), `up`, `try` (take one if available), `count`, `adjust($delta)`, `waiters` (the waiting coroutines, or their number in scalar context) and, from Coro's Perl half, `guard`. `Coro::Signal->new` has `wait`, `send` (wake one waiter, or the next to wait), `broadcast` (wake every waiter) and `awaited`. ## Coro::State - `Coro::State->new(\&sub, @args)` makes a state that runs `sub` when first transferred to; `Coro::State->new` with no sub makes an empty one to save the current state in. A sub that returns ends the program. - `$prev->transfer($next)` saves the running state in `$prev` and continues `$next`. - `$state->call(\&code)` and `$state->eval($string)` run code in the context of another state (for debuggers; the code must not switch). - `$state->swap_defsv` and `swap_defav` exchange the current `$_` or `@_` with the state's; `$state->swap_sv(\$var, \$private)` makes `$var` hold `$private`'s contents whenever that state runs (calling it again with the same two undoes it). - `$state->cancel` destroys the state. - `$state->throw`, `is_new`, `is_zombie` are as for Coro objects. - `$state->rss` is the memory its stacks use, in bytes; `usecount` the number of transfers to it. - `Coro::State::enable_times($bool)` turns on per-coroutine time accounting and returns the previous setting; `$state->times` then returns its real and CPU seconds. - `Coro::State::list` returns every state, Coro objects included. - `$state->trace($flags)` traces sub calls and statements in it, as `Coro::Debug` uses; `$state->is_traced` reads the flags. - C stacks: `$state->has_cctx` says whether it holds one; `Coro::State::force_cctx` gives the running state one; `Coro::State::cctx_count` and `cctx_idle` count those in use and cached; `cctx_max_idle($n)` and `cctx_stacksize($n)` set the cache size (default 4) and the size of new stacks, each returning the old value. - `$state->clone` dies "Coro::State->clone has not been configured into this installation of Coro", as in a default Coro build. The other Coro modules (`Coro::Channel`, `Coro::RWLock`, `Coro::Specific`, `Coro::Timer`, `Coro::AnyEvent`, `Coro::Handle`, `Coro::Debug`, ...) are Coro's Perl modules, unchanged. ## Differences from upstream Two, both where perl 5.44 with XS Coro crashes (t/81-xs-native/Coro/390-or-better.t): - `Coro::State::is_ready(bless {}, 'X')` and the other methods called on a blessed hash that is not a coroutine die "Coro::State object required", as they do for every other non-coroutine. Coro reads the magic of a hash that has none and crashes. - `binmode $fh, ':cede'` with no interval uses the 0.01-second interval Coro's layer falls back to. Coro reads the missing argument and crashes.