Files
wren/modules/core/fiber.html
2021-04-04 19:35:47 +00:00

315 lines
12 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-type" content="text/html;charset=UTF-8" />
<title>Fiber Class &ndash; Wren</title>
<script type="application/javascript" src="../../prism.js" data-manual></script>
<script type="application/javascript" src="../../wren.js"></script>
<link rel="stylesheet" type="text/css" href="../../prism.css" />
<link rel="stylesheet" type="text/css" href="../../style.css" />
<link href='//fonts.googleapis.com/css?family=Source+Sans+Pro:400,700,400italic,700italic|Source+Code+Pro:400|Lato:400|Sanchez:400italic,400' rel='stylesheet' type='text/css'>
<!-- Tell mobile browsers we're optimized for them and they don't need to crop
the viewport. -->
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1"/>
</head>
<body id="top" class="module">
<header>
<div class="page">
<div class="main-column">
<h1><a href="../../">wren</a></h1>
<h2>a classy little scripting language</h2>
</div>
</div>
</header>
<div class="page">
<nav class="big">
<a href="../../"><img src="../../wren.svg" class="logo"></a>
<ul>
<li><a href="../">Back to Modules</a></li>
</ul>
<section>
<h2>core classes</h2>
<ul>
<li><a href="bool.html">Bool</a></li>
<li><a href="class.html">Class</a></li>
<li><a href="fiber.html">Fiber</a></li>
<li><a href="fn.html">Fn</a></li>
<li><a href="list.html">List</a></li>
<li><a href="map.html">Map</a></li>
<li><a href="null.html">Null</a></li>
<li><a href="num.html">Num</a></li>
<li><a href="object.html">Object</a></li>
<li><a href="range.html">Range</a></li>
<li><a href="sequence.html">Sequence</a></li>
<li><a href="string.html">String</a></li>
<li><a href="system.html">System</a></li>
</ul>
</section>
</nav>
<nav class="small">
<table>
<tr>
<td><a href="../">Modules</a></td>
<td><a href="./">core</a></td>
</tr>
<tr>
<td colspan="2"><h2>core classes</h2></td>
</tr>
<tr>
<td>
<ul>
<li><a href="bool.html">Bool</a></li>
<li><a href="class.html">Class</a></li>
<li><a href="fiber.html">Fiber</a></li>
<li><a href="fn.html">Fn</a></li>
<li><a href="list.html">List</a></li>
<li><a href="map.html">Map</a></li>
<li><a href="null.html">Null</a></li>
</ul>
</td>
<td>
<ul>
<li><a href="num.html">Num</a></li>
<li><a href="object.html">Object</a></li>
<li><a href="range.html">Range</a></li>
<li><a href="sequence.html">Sequence</a></li>
<li><a href="string.html">String</a></li>
<li><a href="system.html">System</a></li>
</ul>
</td>
</tr>
</table>
</nav>
<main>
<h1>Fiber Class</h1>
<p>A lightweight coroutine. <a href="../../concurrency.html">Here</a> is a gentle introduction.</p>
<h2>Static Methods <a href="#static-methods" name="static-methods" class="header-anchor">#</a></h2>
<h3>Fiber.<strong>abort</strong>(message) <a href="#fiber.abort(message)" name="fiber.abort(message)" class="header-anchor">#</a></h3>
<p>Raises a runtime error with the provided message:</p>
<pre class="snippet">
Fiber.abort("Something bad happened.")
</pre>
<p>If the message is <code>null</code>, does nothing.</p>
<h3>Fiber.<strong>current</strong> <a href="#fiber.current" name="fiber.current" class="header-anchor">#</a></h3>
<p>The currently executing fiber.</p>
<h3>Fiber.<strong>new</strong>(function) <a href="#fiber.new(function)" name="fiber.new(function)" class="header-anchor">#</a></h3>
<p>Creates a new fiber that executes <code>function</code> in a separate coroutine when the
fiber is run. Does not immediately start running the fiber.</p>
<pre class="snippet">
var fiber = Fiber.new {
System.print("I won't get printed")
}
</pre>
<p><code>function</code> must be a function (an actual <a href="fn.html">Fn</a> instance, not just an object
with a <code>call()</code> method) and it may only take zero or one parameters.</p>
<h3>Fiber.<strong>suspend</strong>() <a href="#fiber.suspend()" name="fiber.suspend()" class="header-anchor">#</a></h3>
<p>Pauses the current fiber, and stops the interpreter. Control returns to the
host application.</p>
<p>Typically, you store a reference to the fiber using <code>Fiber.current</code> before
calling this. The fiber can be resumed later by calling or transferring to that
reference. If there are no references to it, it is eventually garbage collected.</p>
<p>Much like <code>yield()</code>, returns the value passed to <code>call()</code> or <code>transfer()</code> when
the fiber is resumed.</p>
<h3>Fiber.<strong>yield</strong>() <a href="#fiber.yield()" name="fiber.yield()" class="header-anchor">#</a></h3>
<p>Pauses the current fiber and transfers control to the parent fiber. &ldquo;Parent&rdquo;
here means the last fiber that was started using <code>call</code> and not <code>transfer</code>.</p>
<pre class="snippet">
var fiber = Fiber.new {
System.print("Before yield")
Fiber.yield()
System.print("After yield")
}
fiber.call() //> Before yield
System.print("After call") //> After call
fiber.call() //> After yield
</pre>
<p>When resumed, the parent fiber&rsquo;s <code>call()</code> method returns <code>null</code>.</p>
<p>If a yielded fiber is resumed by calling <code>call()</code> or <code>transfer()</code> with an
argument, <code>yield()</code> returns that value.</p>
<pre class="snippet">
var fiber = Fiber.new {
System.print(Fiber.yield()) //> value
}
fiber.call() // Run until the first yield.
fiber.call("value") // Resume the fiber.
</pre>
<p>If it was resumed by calling <code>call()</code> or <code>transfer()</code> with no argument, it
returns <code>null</code>.</p>
<p>If there is no parent fiber to return to, this exits the interpreter. This can
be useful to pause execution until the host application wants to resume it
later.</p>
<pre class="snippet">
Fiber.yield()
System.print("this does not get reached")
</pre>
<h3>Fiber.<strong>yield</strong>(value) <a href="#fiber.yield(value)" name="fiber.yield(value)" class="header-anchor">#</a></h3>
<p>Similar to <code>Fiber.yield</code> but provides a value to return to the parent fiber&rsquo;s
<code>call</code>.</p>
<pre class="snippet">
var fiber = Fiber.new {
Fiber.yield("value")
}
System.print(fiber.call()) //> value
</pre>
<h2>Methods <a href="#methods" name="methods" class="header-anchor">#</a></h2>
<h3><strong>call</strong>() <a href="#call()" name="call()" class="header-anchor">#</a></h3>
<p>Starts or resumes the fiber if it is in a paused state. Equivalent to:</p>
<pre class="snippet">
fiber.call(null)
</pre>
<h3><strong>call</strong>(value) <a href="#call(value)" name="call(value)" class="header-anchor">#</a></h3>
<p>Start or resumes the fiber if it is in a paused state. If the fiber is being
started for the first time, and its function takes a parameter, <code>value</code> is
passed to it.</p>
<pre class="snippet">
var fiber = Fiber.new {|param|
System.print(param) //> begin
}
fiber.call("begin")
</pre>
<p>If the fiber is being resumed, <code>value</code> becomes the returned value of the fiber&rsquo;s
call to <code>yield</code>.</p>
<pre class="snippet">
var fiber = Fiber.new {
System.print(Fiber.yield()) //> resume
}
fiber.call()
fiber.call("resume")
</pre>
<h3><strong>error</strong> <a href="#error" name="error" class="header-anchor">#</a></h3>
<p>The error message that was passed when aborting the fiber, or <code>null</code> if the
fiber has not been aborted.</p>
<pre class="snippet">
var fiber = Fiber.new {
123.badMethod
}
fiber.try()
System.print(fiber.error) //> Num does not implement method 'badMethod'.
</pre>
<h3><strong>isDone</strong> <a href="#isdone" name="isdone" class="header-anchor">#</a></h3>
<p>Whether the fiber&rsquo;s main function has completed and the fiber can no longer be
run. This returns <code>false</code> if the fiber is currently running or has yielded.</p>
<h3><strong>try</strong>() <a href="#try()" name="try()" class="header-anchor">#</a></h3>
<p>Tries to run the fiber. If a runtime error occurs
in the called fiber, the error is captured and is returned as a string.</p>
<pre class="snippet">
var fiber = Fiber.new {
123.badMethod
}
var error = fiber.try()
System.print("Caught error: " + error)
</pre>
<p>If the called fiber raises an error, it can no longer be used.</p>
<h3><strong>try</strong>(value) <a href="#try(value)" name="try(value)" class="header-anchor">#</a></h3>
<p>Tries to run the fiber. If a runtime error occurs
in the called fiber, the error is captured and is returned as a string.
If the fiber is being
started for the first time, and its function takes a parameter, <code>value</code> is
passed to it.</p>
<pre class="snippet">
var fiber = Fiber.new {|value|
value.badMethod
}
var error = fiber.try("just a string")
System.print("Caught error: " + error)
</pre>
<p>If the called fiber raises an error, it can no longer be used.</p>
<h3><strong>transfer</strong>() <a href="#transfer()" name="transfer()" class="header-anchor">#</a></h3>
<p>Pauses execution of the current running fiber, and transfers control to this fiber.</p>
<p><a href="../../concurrency.html#transferring-control">Read more</a> about the difference between <code>call</code> and <code>transfer</code>.
Unlike <code>call</code>, <code>transfer</code> doesn&rsquo;t track the origin of the transfer.</p>
<pre class="snippet">
// keep hold of the fiber we start in
var main = Fiber.current
// create a new fiber, note it doesn't execute yet!
var fiber = Fiber.new {
System.print("inside 'fiber'") //> #2: from #1
main.transfer() //> #3: go back to 'main'
}
fiber.transfer() //> #1: print "inside 'fiber'" via #2
//> this fiber is now paused by #1
System.print("main") //> #4: prints "main", unpaused by #3
</pre>
<h3><strong>transfer</strong>(value) <a href="#transfer(value)" name="transfer(value)" class="header-anchor">#</a></h3>
<p>Pauses execution of the current running fiber, and transfers control to this fiber.</p>
<p>Similar to <code>transfer</code>, but a value can be passed between the fibers.</p>
<pre class="snippet">
// keep hold of the fiber we start in
var main = Fiber.current
// create a new fiber, note it doesn't execute yet
// also note that we're accepting a 'value' parameter
var fiber = Fiber.new {|value|
System.print("in 'fiber' = %(value)") //> #2: in 'fiber' = 5
var result = main.transfer("hello?") //> #3: send to 'message'
System.print("end 'fiber' = %(result)") //> #6: end 'fiber' = 32
}
var message = fiber.transfer(5) //> #1: send to 'value'
System.print("... %(message)") //> #4: ... hello?
fiber.transfer(32) //> #5: send to 'result'
</pre>
<h3><strong>transferError</strong>(error) <a href="#transfererror(error)" name="transfererror(error)" class="header-anchor">#</a></h3>
<p>Transfer to this fiber, but set this fiber into an error state.
The <code>fiber.error</code> value will be populated with the value in <code>error</code>.</p>
<pre class="snippet">
var A = Fiber.new {
System.print("transferred to A") //> #4
B.transferError("error!") //> #5
}
var B = Fiber.new {
System.print("started B") //> #2
A.transfer() //> #3
System.print("should not get here")
}
B.try() //> #1
System.print(B.error) //> #6: prints "error!" from #5
// B fiber can no longer be used
B.call() //> #7: Cannot call an aborted fiber.
</pre>
</main>
</div>
<footer>
<div class="page">
<div class="main-column">
<p>Wren lives
<a href="https://github.com/wren-lang/wren">on GitHub</a>
&mdash; Made with &#x2764; by
<a href="http://journal.stuffwithstuff.com/">Bob Nystrom</a> and
<a href="https://github.com/wren-lang/wren/blob/main/AUTHORS">friends</a>.
</p>
<div class="main-column">
</div>
</footer>
</body>
</html>