<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr" lang="en">
<head>
  <title>the all-thing</title>
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  <link rel="stylesheet" href="/static/style.css" type="text/css" />
  <link rel="alternate" type="application/rss+xml" title="the all-thing RSS feed" href="/index.rss" />
  <link rel="alternate" type="text/plain" title="the all-thing in plain text" href="/index.txt" />
  <script type="text/javascript" src="/static/mootools.js"></script>
  <script type="text/javascript" src="http://music.masanjin.net:9292/waxiest.js"></script>
</head>
<body>

<div id="main">
  <div id="header">
    <h1><a  href="/">the all-thing</a></h1>
    
      <p>Showing only posts labeled "fibers" (<a  href="/label/fibers.rss">rss</a>). <a  href="/index/">See all posts</a>.</p>
    
  </div>
  <div id="sidebar">
    <h3>Recent comments</h3>

    <ul class="sidebar-list">
    
    <li><b><a  href="/whisper-0.5#58174069c046a78e55f02ef81da81e74">Dominique Julia</a></b>
        <i><a  href="/whisper-0.5">Whisper 0.5 released</a></i>
           one week ago
    </li>
    
    <li><b><a  href="/ruby-ncurses-and-thread-blocking#8fa2a0f392d7c0562d630e4936407c11">William Morgan</a></b>
        <i><a  href="/ruby-ncurses-and-thread-blocking">Ruby, Ncurses and blocked threads</a></i>
           three months ago
    </li>
    
    <li><b><a  href="/git-wtf-bf06ab7-released#533654a7a229569e27a6d0afd716c444">William Morgan</a></b>
        <i><a  href="/git-wtf-bf06ab7-released">git wtf bf06ab7 released</a></i>
           three months ago
    </li>
    
    <li><b><a  href="/git-wtf-bf06ab7-released#b7b7a905477674eb6985b34a964a0dca">Joao Nelas</a></b>
        <i><a  href="/git-wtf-bf06ab7-released">git wtf bf06ab7 released</a></i>
           three months ago
    </li>
    
    <li><b><a  href="/ruby-ncurses-and-thread-blocking#b00001114360ac152f87d4ac2a6e0c5b">Ollivier Robert</a></b>
        <i><a  href="/ruby-ncurses-and-thread-blocking">Ruby, Ncurses and blocked threads</a></i>
           three months ago
    </li>
    
    </ul>

    <h3>Authors</h3>
    <ul class="sidebar-list">
    
      <li><a class="author" href="/by/William+Morgan/">William&nbsp;Morgan</a>&nbsp;(65) </li>
    
    </ul>

    <h3>Tags</h3>
    <ul class="sidebar-list">
    
      <li><a class="label" href="/label/releases/">releases</a>&nbsp;(15) </li>
    
      <li><a class="label" href="/label/whisper/">whisper</a>&nbsp;(13) </li>
    
      <li><a class="label" href="/label/git/">git</a>&nbsp;(9) </li>
    
      <li><a class="label" href="/label/stats/">stats</a>&nbsp;(8) </li>
    
      <li><a class="label" href="/label/trollop/">trollop</a>&nbsp;(6) </li>
    
      <li><a class="label" href="/label/ruby/">ruby</a>&nbsp;(6) </li>
    
      <li><a class="label" href="/label/sup/">sup</a>&nbsp;(6) </li>
    
      <li><a class="label" href="/label/git-wtf/">git-wtf</a>&nbsp;(4) </li>
    
      <li><a class="label" href="/label/vm/">vm</a>&nbsp;(4) </li>
    
      <li><a class="label" href="/label/mathml/">mathml</a>&nbsp;(3) </li>
    
      <li><a class="label" href="/label/continuations/">continuations</a>&nbsp;(3) </li>
    
      <li><a class="label" href="/label/ditz/">ditz</a>&nbsp;(3) </li>
    
      <li><a class="label" href="/label/proglang/">proglang</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/optimization/">optimization</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/benchmarks/">benchmarks</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/rubinius/">rubinius</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/inlining/">inlining</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/ubuntu/">ubuntu</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/fibers/">fibers</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/ritex/">ritex</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/ruby1.9/">ruby1.9</a>&nbsp;(2) </li>
    
      <li><a class="label" href="/label/ncurses/">ncurses</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/javascript/">javascript</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/media/">media</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/vim/">vim</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/classification/">classification</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/massachusetts/">massachusetts</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/greasemonkey/">greasemonkey</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/wine/">wine</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/readme/">readme</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/ancient-greek/">ancient-greek</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/web/">web</a>&nbsp;(1) </li>
    
      <li><a class="label" href="/label/current+events/">current&nbsp;events</a>&nbsp;(1) </li>
    
    </ul>

    <h3>Other formats</h3>
    <ul class="sidebar-list">
    <li><a href="/index.rss"><img src="/static/rss-badge.png"/></a></li>
    <li><a href="/index.txt">plain text version</a></li>
    </ul>

    <h3 class="waxiest.author.original">Who is this man?</h3>
    <h3 class="waxiest.author.beautiful" style="display:none">I must find out more about this beautiful creature</h3>
    <h3 class="waxiest.author.beautifulbig" style="display:none">I MUST FIND OUT MORE ABOUT THIS BEAUTIFUL CREATURE</h3>
    <h3 class="waxiest.author.originalbig" style="display:none">WHO IS THIS MAN?</h3>

    <script type="text/javascript">
      var w = waxiest();
      w.optimizeHTMLSection("author", ["original", "beautiful", "beautifulbig", "originalbig"]);
    </script>

    <a href="http://masanjin.net" onClick="w.goalReached('greeting')">William Morgan</a>
  </div>
  <div id="content">
    
  <h2><a  href="/fibers-via-continuations">Fibers via Continuations</a></h2>
  <div class="byline">
    <a  href="/by/William+Morgan/">William Morgan</a>,
    <span title="9 months ago">June  1, 2009  2:47pm</span>
  </div>
  
    <div class="labels"><span class='label'><a  href="/label/ruby/">ruby</a></span> <span class='label'><a  href="/label/ruby1.9/">ruby1.9</a></span> <span class='label'><a  href="/label/fibers/">fibers</a></span> <span class='label'><a  href="/label/continuations/">continuations</a></span> </div>
  
  <p class='first'>In the last post I talked about some <a href="http://all-thing.net/fibers">differences between fibers and
continuations</a>. What may not have been clear is
that continuations are more primitive and flexible than fibers are. In fact,
you can implement fibers using continuations.</p>
<p>Here&#8217;s how. The basic idea is that we want to maintain two variables with
continuations in them, <code>inside</code> and <code>outside</code>. The first one will transfer
execution into the block of code that forms the fiber. The second will transfer
control back to the outside world.</p>
<p>When the outside world calls <code>#resume</code>, we save our continuation point as
<code>outside</code>, and call the current <code>inside</code> continuation. When, within the block,
<code>#yield</code> is called, we save our current continuation point as <code>inside</code>, and
transfer code back to the current <code>outside</code>.</p>
<p>There are a few more details in terms of passing values from <code>#yield</code> to
<code>#resume</code>, handling the return value of the block, and handling excessive
calls to #<code>resume</code>, but that&#8217;s the basic story. Here&#8217;s the code:
<code><pre class="ruby"><span class="ident">require</span> <span class="punct">'</span><span class="string">continuation</span><span class="punct">'</span>

<span class="keyword">class </span><span class="class">CFiber</span>
  <span class="keyword">class </span><span class="class">Error</span> <span class="punct">&lt;</span> <span class="constant">StandardError</span><span class="punct">;</span> <span class="keyword">end</span>

  <span class="keyword">def </span><span class="method">initialize</span> <span class="punct">&amp;</span><span class="ident">block</span>
    <span class="attribute">@block</span> <span class="punct">=</span> <span class="ident">block</span>
    <span class="ident">callcc</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">cc</span><span class="punct">|</span>
      <span class="attribute">@inside</span> <span class="punct">=</span> <span class="ident">cc</span>
      <span class="keyword">return</span>
    <span class="keyword">end</span>
    <span class="attribute">@var</span> <span class="punct">=</span> <span class="attribute">@block</span><span class="punct">.</span><span class="ident">call</span> <span class="constant">self</span>
    <span class="attribute">@inside</span> <span class="punct">=</span> <span class="constant">nil</span>
    <span class="attribute">@outside</span><span class="punct">.</span><span class="ident">call</span>
  <span class="keyword">end</span>

  <span class="keyword">def </span><span class="method">resume</span>
    <span class="keyword">raise</span> <span class="constant">Error</span><span class="punct">,</span> <span class="punct">&quot;</span><span class="string">dead cfiber called!</span><span class="punct">&quot;</span> <span class="keyword">unless</span> <span class="attribute">@inside</span>
    <span class="ident">callcc</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">cc</span><span class="punct">|</span>
      <span class="attribute">@outside</span> <span class="punct">=</span> <span class="ident">cc</span>
      <span class="attribute">@inside</span><span class="punct">.</span><span class="ident">call</span>
    <span class="keyword">end</span>
    <span class="attribute">@var</span>
  <span class="keyword">end</span>

  <span class="keyword">def </span><span class="method">yield</span> <span class="ident">var</span>
    <span class="ident">callcc</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">cc</span><span class="punct">|</span>
      <span class="attribute">@var</span> <span class="punct">=</span> <span class="ident">var</span>
      <span class="attribute">@inside</span> <span class="punct">=</span> <span class="ident">cc</span>
      <span class="attribute">@outside</span><span class="punct">.</span><span class="ident">call</span>
    <span class="keyword">end</span>
  <span class="keyword">end</span>
<span class="keyword">end</span></pre></code></p>
<p>This is also runnable on Ruby 1.8&#8212;just remove the <code>require</code>.</p>
<p>So why does Ruby 1.9 bother to implement fibers, when we can just use
continuations?  I don&#8217;t know what the real answer is, but &#8220;speed&#8221; is at least a
<em>good</em> answer. Let&#8217;s do some some benchmarking to compare the two:</p>
<p><code><pre class="ruby"><span class="ident">require</span> <span class="punct">'</span><span class="string">benchmark</span><span class="punct">'</span>
<span class="ident">n</span> <span class="punct">=</span> <span class="constant">ARGV</span><span class="punct">.</span><span class="ident">shift</span><span class="punct">.</span><span class="ident">to_i</span>
<span class="constant">Benchmark</span><span class="punct">.</span><span class="ident">bm</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">bm</span><span class="punct">|</span>
  <span class="ident">bm</span><span class="punct">.</span><span class="ident">report</span> <span class="punct">&quot;</span><span class="string"> fibers</span><span class="punct">&quot;</span> <span class="keyword">do</span>
    <span class="ident">f</span> <span class="punct">=</span> <span class="constant">Fiber</span><span class="punct">.</span><span class="ident">new</span> <span class="keyword">do</span>
      <span class="ident">x</span><span class="punct">,</span> <span class="ident">y</span> <span class="punct">=</span> <span class="number">0</span><span class="punct">,</span> <span class="number">1</span>
      <span class="ident">loop</span> <span class="keyword">do</span>
        <span class="constant">Fiber</span><span class="punct">.</span><span class="ident">yield</span> <span class="ident">y</span>
        <span class="ident">x</span><span class="punct">,</span> <span class="ident">y</span> <span class="punct">=</span> <span class="ident">y</span><span class="punct">,</span> <span class="ident">x</span> <span class="punct">+</span> <span class="ident">y</span>
      <span class="keyword">end</span>
    <span class="keyword">end</span>

    <span class="ident">n</span><span class="punct">.</span><span class="ident">times</span> <span class="punct">{</span> <span class="punct">|</span><span class="ident">i</span><span class="punct">|</span> <span class="ident">f</span><span class="punct">.</span><span class="ident">resume</span> <span class="punct">}</span>
  <span class="keyword">end</span>

  <span class="ident">bm</span><span class="punct">.</span><span class="ident">report</span> <span class="punct">&quot;</span><span class="string">cfibers</span><span class="punct">&quot;</span> <span class="keyword">do</span>
    <span class="ident">f</span> <span class="punct">=</span> <span class="constant">CFiber</span><span class="punct">.</span><span class="ident">new</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">c</span><span class="punct">|</span>
      <span class="ident">x</span><span class="punct">,</span> <span class="ident">y</span> <span class="punct">=</span> <span class="number">0</span><span class="punct">,</span> <span class="number">1</span>
      <span class="ident">loop</span> <span class="keyword">do</span>
        <span class="ident">c</span><span class="punct">.</span><span class="ident">yield</span> <span class="ident">y</span>
        <span class="ident">x</span><span class="punct">,</span> <span class="ident">y</span> <span class="punct">=</span> <span class="ident">y</span><span class="punct">,</span> <span class="ident">x</span> <span class="punct">+</span> <span class="ident">y</span>
      <span class="keyword">end</span>
    <span class="keyword">end</span>

    <span class="ident">n</span><span class="punct">.</span><span class="ident">times</span> <span class="punct">{</span> <span class="punct">|</span><span class="ident">i</span><span class="punct">|</span> <span class="ident">f</span><span class="punct">.</span><span class="ident">resume</span> <span class="punct">}</span>
  <span class="keyword">end</span>
<span class="keyword">end</span></pre></code></p>
<p>We&#8217;ll start with backporting that code to the Ruby 1.8.7 that Ubuntu provides
(ruby 1.8.7 (2008-08-11 patchlevel 72)). For 10000 Fibonacci numbers, we see:</p>
<table style="margin-left: auto; margin-right: auto;">
	<tr>
		<td>         </td>
		<th>user   </th>
		<th>system </th>
		<th>total  </th>
		<th>real   </th>
	</tr>
	<tr>
		<td> <em>cfibers</em> </td>
		<td style="text-align:right;">0.810000 </td>
		<td style="text-align:right;">0.070000 </td>
		<td style="text-align:right;">0.880000 </td>
		<td style="text-align:right;">0.879930 </td>
	</tr>
</table>
<p>That&#8217;s roughly 11.4kfps (that&#8217;s thousand Fibonacci numbers per second) that we
can produce using continuation-based fibers.</p>
<p>Let&#8217;s try the ancient Ruby 1.9.0 that Ubuntu provides (Ruby 1.9.0 (2008-06-20
revision 17482)):</p>
<table style="margin-left: auto; margin-right: auto;">
	<tr>
		<td>         </td>
		<th>user   </th>
		<th>system </th>
		<th>total  </th>
		<th>real    </th>
	</tr>
	<tr>
		<td> <em>fibers</em> </td>
		<td style="text-align:right;">0.040000 </td>
		<td style="text-align:right;">0.000000 </td>
		<td style="text-align:right;">0.040000 </td>
		<td style="text-align:right;">0.037583 </td>
	</tr>
	<tr>
		<td> <em>cfibers</em> </td>
		<td style="text-align:right;">18.680000 </td>
		<td style="text-align:right;">1.770000 </td>
		<td style="text-align:right;">20.450000 </td>
		<td style="text-align:right;">20.482006 </td>
	</tr>
</table>
<p>Wow, fibers are fast: 250kfps. But things have gotten significantly worse for
cfibers, clocking at a measely 0.489kfps for cfibers.</p>
<p>Finally let&#8217;s try the latest and greatest Ruby 1.9.1 (ruby 1.9.1p129
(2009-05-12 revision 23412)):</p>
<table style="margin-left: auto; margin-right: auto;">
	<tr>
		<td>         </td>
		<th>user   </th>
		<th>system </th>
		<th>total  </th>
		<th>real    </th>
	</tr>
	<tr>
		<td> <em>fibers</em>  </td>
		<td style="text-align:right;">0.040000 </td>
		<td style="text-align:right;">0.000000 </td>
		<td style="text-align:right;">0.040000 </td>
		<td style="text-align:right;">0.035148 </td>
	</tr>
	<tr>
		<td> <em>cfibers</em> </td>
		<td style="text-align:right;">0.150000 </td>
		<td style="text-align:right;">0.000000 </td>
		<td style="text-align:right;">0.150000 </td>
		<td style="text-align:right;">0.155890 </td>
	</tr>
</table>
<p>Fibers are just as fast as before, but continuations have improved
dramatically&#8212;from 11.4kfps to 66.6kfps. Still, native fibers are more than
three times faster.</p>
<p>So perhaps Ruby 1.9.1 is the best of both worlds. When you need fast
non-preemptive concurrency, you can use native fibers; when you need to
implement your own crazy control structures, you can use continuations and be
assured that they&#8217;re still pretty darn fast (at least, as far as Ruby
operations are concerned).</p>
  <div class="comment-link">
    
    <a  href="/fibers-via-continuations#comments">No comments</a>.
  </div>

  <h2><a  href="/fibers">Fibers vs Continuations</a></h2>
  <div class="byline">
    <a  href="/by/William+Morgan/">William Morgan</a>,
    <span title="9 months ago">May 31, 2009  9:20pm</span>
  </div>
  
    <div class="labels"><span class='label'><a  href="/label/ruby1.9/">ruby1.9</a></span> <span class='label'><a  href="/label/ruby/">ruby</a></span> <span class='label'><a  href="/label/fibers/">fibers</a></span> <span class='label'><a  href="/label/continuations/">continuations</a></span> </div>
  
  <p class='first'>Ruby 1.9 has both fibers and continuations. The two are often mentioned in the
same breath. They do vaguely similar-sounding things, and are <a href="http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/19609">implemented in
Ruby 1.9 with similar mechanics underneath the
hood</a>, much
as how <a href="http://www.atdot.net/~ko1/pub/ContinuationFest-ruby.pdf">continuations and threads were implemented with the same underlying
mechanics in Ruby 1.8</a>
[<span class="caps">PDF</span>, p. 14].</p>
<p>But implementation similarities aside, continuations and fibers have very
different semantics. A fiber behaves as a thread without preemption. Like a
thread, you create it, and it eventually dies; unlike a thread, you must
manually call <code>yield</code> and <code>resume</code> to transfer control in and out of it,
instead of just letting the runtime call them for you whenever it feels like
it. Like a thread, when you resume a fiber, you have the same call stack and
heap state (local variables) as when you left.</p>
<p>What&#8217;s nice about fibers is that, since you keep explicit control of the order
of execution, you can get thread-like behavior without all the hassle of
mutexes and synchronization. Of course you have to deal with the hassle of
ordering all your operations, but you at least have the option of avoiding the
fun race-condition game that always seems to crop up in threaded programming.</p>
<p>What about continuations? Instead of fibers&#8217; create, kill, yield, and resume
operations, a continuation only really has two operations: capture and resume.
A continuation is captured once, and may be resumed multiple times. When you
resume a continuation, the call stack is reverted to what it looked like when
it was captured, but the heap state stays the same. There&#8217;s no exit point or
death for a continuation (at least until Ruby gets bounded continuations);
execution simply continues from the capture point.</p>
<p>What&#8217;s nice about continuations is that you can use them to implement control
structures. Loops, exceptions, cross-procedure gotos&#8230; almost every control
structure you can come up with can be implemented with continuations.  In fact,
you can <a href="http://all-thing.net/fibers-via-continuations">implement fibers using
continuations</a>!</p>
<p>Let&#8217;s look at an example. Here&#8217;s the fiber-based Fibonacci computation from
<a href="http://www.infoq.com/news/2007/08/ruby-1-9-fibers">the InfoQ article on Fibers in Ruby
1.9</a>:
<code><pre class="ruby"><span class="ident">fib</span> <span class="punct">=</span> <span class="constant">Fiber</span><span class="punct">.</span><span class="ident">new</span> <span class="keyword">do</span>  
  <span class="ident">x</span><span class="punct">,</span> <span class="ident">y</span> <span class="punct">=</span> <span class="number">0</span><span class="punct">,</span> <span class="number">1</span> 
  <span class="ident">loop</span> <span class="keyword">do</span>  
    <span class="constant">Fiber</span><span class="punct">.</span><span class="ident">yield</span> <span class="ident">y</span> 
    <span class="ident">x</span><span class="punct">,</span> <span class="ident">y</span> <span class="punct">=</span> <span class="ident">y</span><span class="punct">,</span> <span class="ident">x</span> <span class="punct">+</span> <span class="ident">y</span> 
  <span class="keyword">end</span> 
<span class="keyword">end</span> 
<span class="number">20</span><span class="punct">.</span><span class="ident">times</span> <span class="punct">{</span> <span class="ident">puts</span> <span class="ident">fib</span><span class="punct">.</span><span class="ident">resume</span> <span class="punct">}</span></pre></code></p>
<p>Here we call <code>yield</code> from within the fiber once we&#8217;ve computed a number, which
transfers control to the main function, and which prints out the number yielded
and then calls <code>resume</code> to transfer control back to the fiber. A thread version
looks very similar:
<code><pre class="ruby"><span class="ident">require</span> <span class="punct">'</span><span class="string">thread</span><span class="punct">'</span>
<span class="ident">q</span> <span class="punct">=</span> <span class="constant">SizedQueue</span><span class="punct">.</span><span class="ident">new</span> <span class="number">1</span>
<span class="ident">fib</span> <span class="punct">=</span> <span class="constant">Thread</span><span class="punct">.</span><span class="ident">new</span> <span class="keyword">do</span>  
  <span class="ident">x</span><span class="punct">,</span> <span class="ident">y</span> <span class="punct">=</span> <span class="number">0</span><span class="punct">,</span> <span class="number">1</span> 
  <span class="ident">loop</span> <span class="keyword">do</span>  
    <span class="ident">q</span><span class="punct">.</span><span class="ident">push</span> <span class="ident">y</span> 
    <span class="ident">x</span><span class="punct">,</span> <span class="ident">y</span> <span class="punct">=</span> <span class="ident">y</span><span class="punct">,</span> <span class="ident">x</span> <span class="punct">+</span> <span class="ident">y</span> 
  <span class="keyword">end</span> 
<span class="keyword">end</span> 

<span class="number">20</span><span class="punct">.</span><span class="ident">times</span> <span class="punct">{</span> <span class="ident">puts</span> <span class="ident">q</span><span class="punct">.</span><span class="ident">pop</span> <span class="punct">}</span></pre></code></p>
<p>Since we don&#8217;t have explicit control over the scheduling, we implicitly
scheduled the order of operations by using a synchronized <code>SizedQueue</code> data
structure, which blocks the computation thread from computing a new number
until the printing thread is ready to receive it. (There are many ways we
could&#8217;ve accomplished this.)</p>
<p>Here&#8217;s the version using continuations:
<code><pre class="ruby"><span class="ident">require</span> <span class="punct">'</span><span class="string">continuation</span><span class="punct">'</span>
<span class="ident">c</span><span class="punct">,</span> <span class="ident">x</span><span class="punct">,</span> <span class="ident">y</span><span class="punct">,</span> <span class="ident">i</span> <span class="punct">=</span> <span class="ident">callcc</span> <span class="punct">{</span> <span class="punct">|</span><span class="ident">cc</span><span class="punct">|</span> <span class="punct">[</span><span class="ident">cc</span><span class="punct">,</span> <span class="number">0</span><span class="punct">,</span> <span class="number">1</span><span class="punct">,</span> <span class="number">1</span><span class="punct">]</span> <span class="punct">}</span>
<span class="ident">puts</span> <span class="ident">y</span>
<span class="ident">c</span><span class="punct">.</span><span class="ident">call</span> <span class="ident">c</span><span class="punct">,</span> <span class="ident">y</span><span class="punct">,</span> <span class="ident">x</span> <span class="punct">+</span> <span class="ident">y</span><span class="punct">,</span> <span class="ident">i</span> <span class="punct">+</span> <span class="number">1</span> <span class="keyword">if</span> <span class="ident">i</span> <span class="punct">&lt;</span> <span class="number">20</span></pre></code></p>
<p>You&#8217;ll notice there are no loops, and variables are never changed after
assignment. In fact the code is starting to look suspiciously like an inductive
proof, with one line that like a base case and another line that looks like a
recursive case. You can see why continuations make functional-programming
enthusiasts get excited!</p>
<p>This implementation works because resuming the continuation (the call to
<code>c.call</code>) replaces the call stack and point of execution with what they were at
the point it was captured (the call to <code>callcc</code>). In contrast, <code>resume</code>-ing the
fiber moved us back to the point we were when the fiber called <code>yield</code>, and so
the outer <code>loop</code> in the fiber implementation was necessary.</p>
<p>Beyond call stacks, another major difference between fibers and continuations
is the way the heap is treated. Multiple fibers on the same section of code do
not share local variables. Multiple continuations on the same section of code
<em>do</em>. Here&#8217;s a brief example. First, the fibers version:</p>
<p><code><pre class="ruby"><span class="ident">fib</span> <span class="punct">=</span> <span class="punct">(</span><span class="number">0</span> <span class="punct">...</span> <span class="number">5</span><span class="punct">).</span><span class="ident">map</span> <span class="keyword">do</span> <span class="punct">|</span><span class="ident">i</span><span class="punct">|</span>
  <span class="constant">Fiber</span><span class="punct">.</span><span class="ident">new</span> <span class="keyword">do</span>
    <span class="ident">x</span> <span class="punct">=</span> <span class="number">0</span>
    <span class="constant">Fiber</span><span class="punct">.</span><span class="ident">yield</span> <span class="ident">x</span>
    <span class="ident">x</span> <span class="punct">+=</span> <span class="number">1</span>
  <span class="keyword">end</span>
<span class="keyword">end</span>

<span class="ident">fib</span><span class="punct">.</span><span class="ident">each</span> <span class="punct">{</span> <span class="punct">|</span><span class="ident">f</span><span class="punct">|</span> <span class="ident">puts</span> <span class="ident">f</span><span class="punct">.</span><span class="ident">resume</span> <span class="punct">}</span></pre></code></p>
<p>We create five fibers, and call <code>resume</code> on them once each. As you&#8217;d expect,
this prints out a series of 0&#8217;s. The variable <code>x</code> is not shared between the
multiple fibers. Of course, the fiber constructor here is a block, and blocks
are closures, so we could <em>make</em> them share state by moving the <code>x = 0</code> line
outside the <code>map</code> line. But that&#8217;s a result of having closures, not of fibers
per se.</p>
<p>Let&#8217;s try an example with multiple continuations, all jumping into the same point in the code:
<code><pre class="ruby"><span class="ident">require</span> <span class="punct">'</span><span class="string">continuation</span><span class="punct">'</span>

<span class="ident">x</span> <span class="punct">=</span> <span class="number">0</span>
<span class="ident">c</span> <span class="punct">=</span> <span class="ident">callcc</span> <span class="punct">{</span> <span class="punct">|</span><span class="ident">cc</span><span class="punct">|</span> <span class="ident">cc</span> <span class="punct">}</span>
<span class="ident">d</span> <span class="punct">=</span> <span class="ident">callcc</span> <span class="punct">{</span> <span class="punct">|</span><span class="ident">cc</span><span class="punct">|</span> <span class="ident">cc</span> <span class="punct">}</span> <span class="keyword">if</span> <span class="ident">c</span>
<span class="ident">e</span> <span class="punct">=</span> <span class="ident">callcc</span> <span class="punct">{</span> <span class="punct">|</span><span class="ident">cc</span><span class="punct">|</span> <span class="ident">cc</span> <span class="punct">}</span> <span class="keyword">if</span> <span class="ident">c</span> <span class="punct">&amp;&amp;</span> <span class="ident">d</span>
<span class="ident">f</span> <span class="punct">=</span> <span class="ident">callcc</span> <span class="punct">{</span> <span class="punct">|</span><span class="ident">cc</span><span class="punct">|</span> <span class="ident">cc</span> <span class="punct">}</span> <span class="keyword">if</span> <span class="ident">c</span> <span class="punct">&amp;&amp;</span> <span class="ident">d</span> <span class="punct">&amp;&amp;</span> <span class="ident">e</span>
<span class="ident">x</span> <span class="punct">+=</span> <span class="number">1</span>

<span class="ident">puts</span> <span class="ident">x</span>
<span class="ident">c</span><span class="punct">.</span><span class="ident">call</span> <span class="keyword">if</span> <span class="ident">c</span>
<span class="ident">d</span><span class="punct">.</span><span class="ident">call</span> <span class="keyword">if</span> <span class="ident">d</span>
<span class="ident">e</span><span class="punct">.</span><span class="ident">call</span> <span class="keyword">if</span> <span class="ident">e</span>
<span class="ident">f</span><span class="punct">.</span><span class="ident">call</span> <span class="keyword">if</span> <span class="ident">f</span></pre></code></p>
<p>We initialize <code>x</code> to 0, create 4 separate continuations, add one to <code>x</code>, and
call the continuations in order. (The postfix <code>if</code> statements ensure that the
continuations variables aren&#8217;t set or called more than once. Calling <code>c.call</code>
without arguments will jump back to the <code>c = callcc</code> line and set <code>c</code> to
<code>nil</code>.)</p>
<p>Silly, but it illustrates the point: the output is &#8220;1 2 3 4 5&#8221;, meaning that
the four continuations all share the same heap. When <code>d</code> is called, its <code>x</code> is
the same as the <code>x</code> of <code>c</code>, and even though it was 0 when <code>d</code> was captured, it
has since been modified by the resumption of <code>c</code>. When <code>e</code> is called, its <code>x</code>
is also the same <code>x</code>, and so on. (In fact this whole example depends on this
behavior&#8212;each of the continuation variables are only set once, and must
&#8220;retain&#8221; their value across all rentries to continuations above them.)</p>
<p>In additon to multiple continuations being able to share state, the converse is
true too: multiple resumes on the same continuation will share state:
<code><pre class="ruby"><span class="ident">require</span> <span class="punct">'</span><span class="string">continuation</span><span class="punct">'</span>

<span class="ident">x</span> <span class="punct">=</span> <span class="number">0</span>
<span class="ident">c</span> <span class="punct">=</span> <span class="ident">callcc</span> <span class="punct">{</span> <span class="punct">|</span><span class="ident">cc</span><span class="punct">|</span> <span class="ident">cc</span> <span class="punct">}</span>
<span class="ident">x</span> <span class="punct">+=</span> <span class="number">1</span>
<span class="ident">puts</span> <span class="ident">x</span>
<span class="ident">c</span><span class="punct">.</span><span class="ident">call</span> <span class="ident">c</span> <span class="keyword">while</span> <span class="ident">x</span> <span class="punct">&lt;</span> <span class="number">5</span></pre></code></p>
<p>This outputs the same thing as the examples above.</p>
<p>Hopefully that clears up some of the confusion. Here&#8217;s the summary:</p>
<table style="margin-left: auto; margin-right: auto;">
	<tr>
		<th>Fibers            </th>
		<th>Continuations       </th>
	</tr>
	<tr>
		<td style="vertical-align:top;">Four operations: create, exit, yield, resume. </td>
		<td style="vertical-align:top;">Two operations: capture and resume. </td>
	</tr>
	<tr>
		<td style="vertical-align:top;">Upon resume, call stack is wherever it was at the last yield. </td>
		<td style="vertical-align:top;">Upon resume, call stack is where it was when captured. </td>
	</tr>
	<tr>
		<td style="vertical-align:top;">Do not share state except via closure. </td>
		<td style="vertical-align:top;">Multiple continuations and multiple invocations of the same continuation can share state. </td>
	</tr>
</table>
  <div class="comment-link">
    
    <a  href="/fibers#comments">One comment by <b>William Morgan</b></a>.
  </div>




  </div>

  <div id="footer" style="margin: 0px;">
    Served up by <a href="http://masanjin.net/whisper/">Whisper</a>. Yes!
  </div>
</div>
</body>
</html>
