mirror of https://github.com/svaarala/duktape.git
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.
97 lines
3.6 KiB
97 lines
3.6 KiB
<h1 id="coroutines">Coroutines</h1>
|
|
|
|
<p><b>(This section is incomplete.)</b></p>
|
|
|
|
<h2>Overview of coroutines</h2>
|
|
|
|
<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 <code>new Duktape.Thread()</code>, 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 <code>Duktape.Thread.resume()</code> 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 <code>Duktape.Thread.yield()</code>
|
|
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 a yield is possible.
|
|
In short, a coroutine can only yield if its entire active call stack consists
|
|
of plain Ecmascript-to-Ecmascript calls. The following prevent a yield if
|
|
they are present anywhere in the yielding coroutine's call stack:</p>
|
|
<ul>
|
|
<li>a Duktape/C function call</li>
|
|
<li>a constructor call</li>
|
|
<li>a getter/setter call</li>
|
|
<li>an <code>eval()</code> call</li>
|
|
<li><code>Function.prototype.call()</code> or <code>Function.prototype.apply()</code></li>
|
|
<li>a finalizer call</li>
|
|
</ul>
|
|
|
|
<h2>Example</h2>
|
|
|
|
<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 = Duktape.Thread.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 = new Duktape.Thread(yielder);
|
|
|
|
print('resume test');
|
|
print('yielded with', Duktape.Thread.resume(t, 'foo'));
|
|
print('yielded with', Duktape.Thread.resume(t, 'bar'));
|
|
print('yielded with', Duktape.Thread.resume(t, 'quux'));
|
|
print('yielded with', Duktape.Thread.resume(t, 'baz'));
|
|
print('finished');
|
|
</pre>
|
|
|
|
<p>When executed with the <code>duk</code> 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>
|
|
|
|
|