You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

88 lines
3.1 KiB

<h2 id="coroutines">Coroutines</h2>
<p><b>(This section is incomplete.)</b></p>
<h3>Overview of coroutines</h3>
<p>Duktape has a support for simple coroutines. Execution is strictly nesting:
coroutine A resumes or initiates coroutine B, coroutine B runs until it yields
or finishes (either successfully or through an uncaught error), after which
coroutine A continues execution with the yield result.</p>
<p>Coroutines are created with <tt>__duk__.spawn()</tt>, which gets as its sole
argument the initial function where the new coroutine begins execution on its
first resume. The resume argument becomes the initial function's first (and
only) argument value.</p>
<p>A coroutine is resumed using <tt>__duk__.resume()</tt> which takes the
following arguments: the coroutine to resume, the resume value, and (optionally)
a flag indicating whether the resume value is an ordinary value or an error to
be injected into the target coroutine. Injecting an error means that the resume
value will be "thrown" at the site of the target coroutine's last yield operation.
In other words, instead of returning with an ordinary value, the yield will
seemingly throw an error.</p>
<p>A coroutine yields its current execution using <tt>__duk__.yield()</tt> which
takes as its arguments: the value to yield, and (optionally) a flag indicating
whether the yield value is an ordinary value or an error to be thrown in the
context of the resuming coroutine. In other words, an error value causes the
resume operation to seemingly throw an error instead of returning an ordinary
value.</p>
<p>If a coroutine exists successfully, i.e. the initial function finishes by
returning a value, it is handled similarly to a yield with the return value.
If a coroutine exists because of an uncaught error, it is handled similarly
to a yield with the error: the resume operation will rethrow that error in
the resuming coroutine's context. In either case the coroutine which has
finished can no longer be resumed; attempt to do so will cause a TypeError.</p>
<p>There are currently strict limitations on when resume/yield are possible.
See <a href="#limitations">Limitations</a>.</p>
<h3>Example</h3>
<p>A simple example of the basic mechanics of spawning, resuming, and yielding:</p>
<pre class="ecmascript-code">
// coroutine.js
function yielder(x) {
var yield = __duk__.yield;
print('yielder starting');
print('yielder arg:', x);
print('resumed with', yield(1));
print('resumed with', yield(2));
print('resumed with', yield(3));
print('yielder ending');
return 123;
}
var t = __duk__.spawn(yielder);
print('resume test');
print('yielded with', __duk__.resume(t, 'foo'));
print('yielded with', __duk__.resume(t, 'bar'));
print('yielded with', __duk__.resume(t, 'quux'));
print('yielded with', __duk__.resume(t, 'baz'));
print('finished');
</pre>
<p>When executed with the <tt>duk</tt> command line tool, this prints:</p>
<pre>
$ duk coroutine.js
resume test
yielder starting
yielder arg: foo
yielded with 1
resumed with bar
yielded with 2
resumed with quux
yielded with 3
resumed with baz
yielder ending
yielded with 123
finished
</pre>