You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
<h1id='The_concept_of_fibration_h'><imgsrc='/share/src/web/images/minus.gif' id='The concept of fibration' onclick='toggle(this,"The_concept_of_fibration_d")' alt='+'/> 1 The concept of fibration</h1><divid='The_concept_of_fibration_d' style='display:block'>
<p>I will show a simple low level example of coroutines, it will be a
399
+
simple pipeline consisting of a source, a transducer, a limiter, and a sink.
400
+
</p><p>First we have our source, which just write all the integers starting from 0
401
+
down the channel <code>inp</code>. The type <code>%>int</code> is an output channel endpoint
402
+
for <code>int</code>.
403
+
</p><p><preclass='flxbg'><spanclass="lineno" id=line1></span><spanclass="big_keyword" title="Define a procedure, a function with side-effects not returning a value">proc</span> source (out: %><spanclass="library" title="binding of C int type">int</span>) () {
404
+
<spanclass="lineno" id=line2></span><spanclass="big_keyword" title="Define a mutable variable">var</span> i = 0;
<spanclass="lineno" id=line4></span><spanclass="library" title="Print a string to a stream">write</span> (out,i);
407
+
<spanclass="lineno" id=line5></span> ++i;
408
+
<spanclass="lineno" id=line6></span><spanclass="small_keyword" title="end of body">done</span>
409
+
<spanclass="lineno" id=line7></span> }
410
+
</pre></p><p>Now we have a simple sink, which just prints everything it reads:
411
+
</p><p><preclass='flxbg'><spanclass="lineno" id=line1></span><spanclass="big_keyword" title="Define a procedure, a function with side-effects not returning a value">proc</span> sink (inp: %<<spanclass="library" title="binding of C int type">int</span>) () {
<spanclass="lineno" id=line3></span><spanclass="big_keyword" title="Define a mutable variable">var</span> i = read inp;
414
+
<spanclass="lineno" id=line4></span><spanclass="library" title="Print a string to standard output with newline appended">println</span>$ i;
415
+
<spanclass="lineno" id=line5></span><spanclass="small_keyword" title="end of body">done</span>
416
+
<spanclass="lineno" id=line6></span> }
417
+
</pre></p><p>You should note the extra unit parameter <code>()</code>. After the input is bound, the resulting
418
+
procedure will have type
419
+
</p><p><preclass='flxbg'><spanclass="lineno" id=line1></span><spanclass="library" title="Type with one values (), the empty tuple">unit</span> -> <spanclass="library" title="Type with one values (), the empty tuple">unit</span>
420
+
</pre></p><p>which is the type required to spawn fibre from a coroutine.
421
+
</p><p>Now we have a transducer which writes the square of every integer it reads.
422
+
</p><p><preclass='flxbg'><spanclass="lineno" id=line1></span><spanclass="big_keyword" title="Define a procedure, a function with side-effects not returning a value">proc</span> squarer (inp: %<<spanclass="library" title="binding of C int type">int</span>, out: %><spanclass="library" title="binding of C int type">int</span>) () {
<spanclass="lineno" id=line3></span><spanclass="big_keyword" title="Define a mutable variable">var</span> i = read inp;
425
+
<spanclass="lineno" id=line4></span><spanclass="library" title="Print a string to a stream">write</span> (out, i * I);
426
+
<spanclass="lineno" id=line5></span><spanclass="small_keyword" title="end of body">done</span>
427
+
<spanclass="lineno" id=line6></span> }
428
+
</pre></p><p>You should notice the previous three components were all infinite loops.
429
+
Since we don't want our demo to run forever we will throw in a limiter chip:
430
+
</p><p><preclass='flxbg'><spanclass="lineno" id=line1></span><spanclass="big_keyword" title="Define a procedure, a function with side-effects not returning a value">proc</span> limiter (<spanclass="big_keyword" title="Define a mutable variable">var</span> limit: <spanclass="library" title="binding of C int type">int</span>) (inp: %<<spanclass="library" title="binding of C int type">int</span>, out: %><spanclass="library" title="binding of C int type">int</span>) () {
<spanclass="lineno" id=line3></span><spanclass="big_keyword" title="Define a mutable variable">var</span> i = read inp;
433
+
<spanclass="lineno" id=line4></span><spanclass="library" title="Print a string to a stream">write</span> (out, i);
434
+
<spanclass="lineno" id=line5></span> --limit;
435
+
<spanclass="lineno" id=line6></span><spanclass="small_keyword" title="end of body">done</span>
436
+
<spanclass="lineno" id=line7></span> };
437
+
</pre></p><p>This procedure drops through, but it cannot return control, because
438
+
there is nowhere to return it to, so it has, in effect, committed
439
+
suicide implicitly.
440
+
</p><p><preclass='flxbg'><spanclass="lineno" id=line1></span> Now we need have four components so we need three channels <spanclass="small_keyword" title="substring range separator">to</span> connect them:
441
+
<spanclass="lineno" id=line2></span><spanclass="big_keyword" title="Define a procedure, a function with side-effects not returning a value">proc</span> run_pipeline() {
442
+
<spanclass="lineno" id=line3></span><spanclass="comment">// make channels</span>
443
+
<spanclass="lineno" id=line4></span><spanclass="big_keyword" title="Define a mutable variable">var</span> i1,o1 = mk_ioschannel_pair[<spanclass="library" title="binding of C int type">int</span>]();
444
+
<spanclass="lineno" id=line5></span><spanclass="big_keyword" title="Define a mutable variable">var</span> i2,o2 = mk_ioschannel_pair[<spanclass="library" title="binding of C int type">int</span>]();
445
+
<spanclass="lineno" id=line6></span><spanclass="big_keyword" title="Define a mutable variable">var</span> i3,o3 = mk_ioschannel_pair[<spanclass="library" title="binding of C int type">int</span>]();
446
+
<spanclass="lineno" id=line7></span>
447
+
<spanclass="lineno" id=line8></span><spanclass="comment">// make coroutines by binding the channels</span>
448
+
<spanclass="lineno" id=line9></span><spanclass="big_keyword" title="Define a mutable variable">var</span> d1 = source(o1);
449
+
<spanclass="lineno" id=line10></span><spanclass="big_keyword" title="Define a mutable variable">var</span> d2 = squarer(i1,o2);
</pre></p></div><h1id='The_concept_of_fibration_h'><imgsrc='/share/src/web/images/minus.gif' id='The concept of fibration' onclick='toggle(this,"The_concept_of_fibration_d")' alt='+'/> 2 The concept of fibration</h1><divid='The_concept_of_fibration_d' style='display:block'>
394
462
<p>A <em>coroutine system</em> is a collection of processes called <em>fibres</em>
395
463
with these properties:
396
464
<ul>
397
465
<li>Exactly one process can be <em>running</em> at once, the others are said to be <em>suspended</em></li>
398
466
<li>Control cannot be pre-empted, but is yielded voluntarily</li>
399
467
</ul>
400
-
In our system, there are four principle operations:
468
+
In our system, there are four principle operations which yield control:
401
469
<ol>
402
470
<li><em>spawn</em> a new fibre</li>
403
471
<li><em>read</em> from a channel</li>
@@ -422,11 +490,15 @@ <h1 id='The_concept_of_fibration_h'><img src='/share/src/web/images/minus.gif' i
422
490
then one is selected, the data to be written is tranfered from the writer to the reader,
423
491
the fibre is removed from association with the channel,
424
492
and both the running and reader fibre are made active.
493
+
Otherwise if there is no readers waiting on the channel, the writer is
494
+
suspended and put on the channel.
425
495
</p><p>When a read operation is performed on a channel by the running fibre,
426
496
if there are fibres on the channel which are waiting to write
427
497
then one is selected, the data to be written is transfered from the writer to the reader,
428
498
fibre, the fibre is removed from association with the channel,
429
499
and both the running and reader fibre are made active.
500
+
Otherwise if there is no writers waiting on the channel, the writer is
501
+
suspended and put on the channel.
430
502
</p><p>When a fibre commits suicide, it is removed as the running fibre.
431
503
</p><p>When a new fibre is spawned, both the spawner and spawnee are made active.
432
504
</p><p>When there is no running fibre, then if an active fibre exists,
@@ -447,13 +519,13 @@ <h1 id='The_concept_of_fibration_h'><img src='/share/src/web/images/minus.gif' i
447
519
</p><p>In addition, I/O transfers always result in the reader proceeding,
448
520
to give it a chance to actually fetch the data before the write
0 commit comments