Skip to content

Commit 463a9da

Browse files
committed
experiment
1 parent bcda866 commit 463a9da

File tree

2 files changed

+174
-13
lines changed

2 files changed

+174
-13
lines changed

corout.fdoc

Lines changed: 90 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,97 @@
11
@title coroutines
2+
@h1 A low level example.
3+
I will show a simple low level example of coroutines, it will be a
4+
simple pipeline consisting of a source, a transducer, a limiter, and a sink.
5+
6+
First we have our source, which just write all the integers starting from 0
7+
down the channel @{inp}. The type @{%>int} is an output channel endpoint
8+
for @{int}.
9+
10+
@felix
11+
proc source (out: %>int) () {
12+
var i = 0;
13+
while true do
14+
write (out,i);
15+
++i;
16+
done
17+
}
18+
@
19+
20+
Now we have a simple sink, which just prints everything it reads:
21+
@felix
22+
proc sink (inp: %<int) () {
23+
while true do
24+
var i = read inp;
25+
println$ i;
26+
done
27+
}
28+
@
29+
You should note the extra unit parameter @{()}. After the input is bound, the resulting
30+
procedure will have type
31+
@felix
32+
unit -> unit
33+
@
34+
which is the type required to spawn fibre from a coroutine.
35+
36+
Now we have a transducer which writes the square of every integer it reads.
37+
@felix
38+
proc squarer (inp: %<int, out: %>int) () {
39+
while true do
40+
var i = read inp;
41+
write (out, i * I);
42+
done
43+
}
44+
@
45+
46+
You should notice the previous three components were all infinite loops.
47+
Since we don't want our demo to run forever we will throw in a limiter chip:
48+
@felix
49+
proc limiter (var limit: int) (inp: %<int, out: %>int) () {
50+
while limit > 0 do
51+
var i = read inp;
52+
write (out, i);
53+
--limit;
54+
done
55+
};
56+
@
57+
This procedure drops through, but it cannot return control, because
58+
there is nowhere to return it to, so it has, in effect, committed
59+
suicide implicitly.
60+
61+
@felix
62+
Now we need have four components so we need three channels to connect them:
63+
proc run_pipeline() {
64+
// make channels
65+
var i1,o1 = mk_ioschannel_pair[int]();
66+
var i2,o2 = mk_ioschannel_pair[int]();
67+
var i3,o3 = mk_ioschannel_pair[int]();
68+
69+
// make coroutines by binding the channels
70+
var d1 = source(o1);
71+
var d2 = squarer(i1,o2);
72+
var d3 = limiter 8 (i2,o3);
73+
var d4 = sink (i3);
74+
75+
// spawn coroutines as fibres
76+
spawn_fthread d1;
77+
spawn_fthread d2;
78+
spawn_fthread d3;
79+
spawn_fthread d4;
80+
81+
// exit
82+
}
83+
@
84+
85+
86+
287
@h1 The concept of fibration
388
A <em>coroutine system</em> is a collection of processes called <em>fibres</em>
489
with these properties:
590
<ul>
691
<li>Exactly one process can be <em>running</em> at once, the others are said to be <em>suspended</em></li>
792
<li>Control cannot be pre-empted, but is yielded voluntarily</li>
893
</ul>
9-
In our system, there are four principle operations:
94+
In our system, there are four principle operations which yield control:
1095
<ol>
1196
<li><em>spawn</em> a new fibre</li>
1297
<li><em>read</em> from a channel</li>
@@ -33,12 +118,16 @@ if there are fibres on the channel which are waiting to read
33118
then one is selected, the data to be written is tranfered from the writer to the reader,
34119
the fibre is removed from association with the channel,
35120
and both the running and reader fibre are made active.
121+
Otherwise if there is no readers waiting on the channel, the writer is
122+
suspended and put on the channel.
36123

37124
When a read operation is performed on a channel by the running fibre,
38125
if there are fibres on the channel which are waiting to write
39126
then one is selected, the data to be written is transfered from the writer to the reader,
40127
fibre, the fibre is removed from association with the channel,
41128
and both the running and reader fibre are made active.
129+
Otherwise if there is no writers waiting on the channel, the writer is
130+
suspended and put on the channel.
42131

43132
When a fibre commits suicide, it is removed as the running fibre.
44133

tmp.html

Lines changed: 84 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@
305305
}
306306
}
307307
var allbuttons = [
308+
"A low level example.",
308309
"The concept of fibration",
309310
"next",
310311
"high",
@@ -370,17 +371,20 @@
370371
<!--Left Margin Toc-->
371372
<div id="leftmargintoc">
372373
<!--Left Margin Toc Main Contents-->
373-
<div class=m1 onclick="mshow('menu1','#The concept of fibration_h')"> <a href="#The_concept_of_fibration_h">The concept of fibration</a></div>
374+
<div class=m1 onclick="mshow('menu1','#A low level example._h')"> <a href="#A_low_level_example._h">A low level example.</a></div>
374375
<div class=sm id=menu1>
375-
<div class=m2><a href="#next_h">next</a></div>
376376
</div>
377-
<div class=m1 onclick="mshow('menu2','#high_h')"> <a href="#high_h">high</a></div>
377+
<div class=m1 onclick="mshow('menu2','#The concept of fibration_h')"> <a href="#The_concept_of_fibration_h">The concept of fibration</a></div>
378378
<div class=sm id=menu2>
379+
<div class=m2><a href="#next_h">next</a></div>
380+
</div>
381+
<div class=m1 onclick="mshow('menu3','#high_h')"> <a href="#high_h">high</a></div>
382+
<div class=sm id=menu3>
379383
<div class=m2><a href="#med1_h">med1</a></div>
380384
<div class=m2><a href="#med2_h">med2</a></div>
381385
<div class=m2><a href="#med3_h">med3</a></div>
382386
</div>
383-
<script>counter_max=2;</script>
387+
<script>counter_max=3;</script>
384388
</div>
385389
<!--End Left Margin Toc-->
386390

@@ -390,14 +394,78 @@
390394
<span id="right" class="rightpanel">
391395
<div class="maincontent">
392396
<!--Main Content Body-->
393-
<h1 id='The_concept_of_fibration_h'><img src='/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><div id='The_concept_of_fibration_d' style='display:block'>
397+
<h1 id='A_low_level_example._h'><img src='/share/src/web/images/minus.gif' id='A low level example.' onclick='toggle(this,"A_low_level_example._d")' alt='+'/> 1 A low level example.</h1><div id='A_low_level_example._d' style='display:block'>
398+
<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><pre class='flxbg'><span class="lineno" id=line1></span> <span class="big_keyword" title="Define a procedure, a function with side-effects not returning a value">proc</span> source (out: %&gt;<span class="library" title="binding of C int type">int</span>) () {
404+
<span class="lineno" id=line2></span> <span class="big_keyword" title="Define a mutable variable">var</span> i = 0;
405+
<span class="lineno" id=line3></span> <span class="small_keyword" title="while loop">while</span> <span class="library" title="truth value">true</span> <span class="small_keyword" title="imperative code begins">do</span>
406+
<span class="lineno" id=line4></span> <span class="library" title="Print a string to a stream">write</span> (out,i);
407+
<span class="lineno" id=line5></span> ++i;
408+
<span class="lineno" id=line6></span> <span class="small_keyword" title="end of body">done</span>
409+
<span class="lineno" id=line7></span> }
410+
</pre></p><p>Now we have a simple sink, which just prints everything it reads:
411+
</p><p><pre class='flxbg'><span class="lineno" id=line1></span> <span class="big_keyword" title="Define a procedure, a function with side-effects not returning a value">proc</span> sink (inp: %&lt;<span class="library" title="binding of C int type">int</span>) () {
412+
<span class="lineno" id=line2></span> <span class="small_keyword" title="while loop">while</span> <span class="library" title="truth value">true</span> <span class="small_keyword" title="imperative code begins">do</span>
413+
<span class="lineno" id=line3></span> <span class="big_keyword" title="Define a mutable variable">var</span> i = read inp;
414+
<span class="lineno" id=line4></span> <span class="library" title="Print a string to standard output with newline appended">println</span>$ i;
415+
<span class="lineno" id=line5></span> <span class="small_keyword" title="end of body">done</span>
416+
<span class="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><pre class='flxbg'><span class="lineno" id=line1></span> <span class="library" title="Type with one values (), the empty tuple">unit</span> -&gt; <span class="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><pre class='flxbg'><span class="lineno" id=line1></span> <span class="big_keyword" title="Define a procedure, a function with side-effects not returning a value">proc</span> squarer (inp: %&lt;<span class="library" title="binding of C int type">int</span>, out: %&gt;<span class="library" title="binding of C int type">int</span>) () {
423+
<span class="lineno" id=line2></span> <span class="small_keyword" title="while loop">while</span> <span class="library" title="truth value">true</span> <span class="small_keyword" title="imperative code begins">do</span>
424+
<span class="lineno" id=line3></span> <span class="big_keyword" title="Define a mutable variable">var</span> i = read inp;
425+
<span class="lineno" id=line4></span> <span class="library" title="Print a string to a stream">write</span> (out, i * I);
426+
<span class="lineno" id=line5></span> <span class="small_keyword" title="end of body">done</span>
427+
<span class="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><pre class='flxbg'><span class="lineno" id=line1></span> <span class="big_keyword" title="Define a procedure, a function with side-effects not returning a value">proc</span> limiter (<span class="big_keyword" title="Define a mutable variable">var</span> limit: <span class="library" title="binding of C int type">int</span>) (inp: %&lt;<span class="library" title="binding of C int type">int</span>, out: %&gt;<span class="library" title="binding of C int type">int</span>) () {
431+
<span class="lineno" id=line2></span> <span class="small_keyword" title="while loop">while</span> limit &gt; 0 <span class="small_keyword" title="imperative code begins">do</span>
432+
<span class="lineno" id=line3></span> <span class="big_keyword" title="Define a mutable variable">var</span> i = read inp;
433+
<span class="lineno" id=line4></span> <span class="library" title="Print a string to a stream">write</span> (out, i);
434+
<span class="lineno" id=line5></span> --limit;
435+
<span class="lineno" id=line6></span> <span class="small_keyword" title="end of body">done</span>
436+
<span class="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><pre class='flxbg'><span class="lineno" id=line1></span> Now we need have four components so we need three channels <span class="small_keyword" title="substring range separator">to</span> connect them:
441+
<span class="lineno" id=line2></span> <span class="big_keyword" title="Define a procedure, a function with side-effects not returning a value">proc</span> run_pipeline() {
442+
<span class="lineno" id=line3></span> <span class="comment">// make channels</span>
443+
<span class="lineno" id=line4></span> <span class="big_keyword" title="Define a mutable variable">var</span> i1,o1 = mk_ioschannel_pair[<span class="library" title="binding of C int type">int</span>]();
444+
<span class="lineno" id=line5></span> <span class="big_keyword" title="Define a mutable variable">var</span> i2,o2 = mk_ioschannel_pair[<span class="library" title="binding of C int type">int</span>]();
445+
<span class="lineno" id=line6></span> <span class="big_keyword" title="Define a mutable variable">var</span> i3,o3 = mk_ioschannel_pair[<span class="library" title="binding of C int type">int</span>]();
446+
<span class="lineno" id=line7></span>
447+
<span class="lineno" id=line8></span> <span class="comment">// make coroutines by binding the channels</span>
448+
<span class="lineno" id=line9></span> <span class="big_keyword" title="Define a mutable variable">var</span> d1 = source(o1);
449+
<span class="lineno" id=line10></span> <span class="big_keyword" title="Define a mutable variable">var</span> d2 = squarer(i1,o2);
450+
<span class="lineno" id=line11></span> <span class="big_keyword" title="Define a mutable variable">var</span> d3 = limiter 8 (i2,o3);
451+
<span class="lineno" id=line12></span> <span class="big_keyword" title="Define a mutable variable">var</span> d4 = sink (i3);
452+
<span class="lineno" id=line13></span>
453+
<span class="lineno" id=line14></span> <span class="comment">// spawn coroutines as fibres</span>
454+
<span class="lineno" id=line15></span> <span class="big_keyword" title="Spawn a cooperative fibre">spawn_fthread</span> d1;
455+
<span class="lineno" id=line16></span> <span class="big_keyword" title="Spawn a cooperative fibre">spawn_fthread</span> d2;
456+
<span class="lineno" id=line17></span> <span class="big_keyword" title="Spawn a cooperative fibre">spawn_fthread</span> d3;
457+
<span class="lineno" id=line18></span> <span class="big_keyword" title="Spawn a cooperative fibre">spawn_fthread</span> d4;
458+
<span class="lineno" id=line19></span>
459+
<span class="lineno" id=line20></span> <span class="comment">// exit</span>
460+
<span class="lineno" id=line21></span> }
461+
</pre></p></div><h1 id='The_concept_of_fibration_h'><img src='/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><div id='The_concept_of_fibration_d' style='display:block'>
394462
<p>A <em>coroutine system</em> is a collection of processes called <em>fibres</em>
395463
with these properties:
396464
<ul>
397465
<li>Exactly one process can be <em>running</em> at once, the others are said to be <em>suspended</em></li>
398466
<li>Control cannot be pre-empted, but is yielded voluntarily</li>
399467
</ul>
400-
In our system, there are four principle operations:
468+
In our system, there are four principle operations which yield control:
401469
<ol>
402470
<li><em>spawn</em> a new fibre</li>
403471
<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
422490
then one is selected, the data to be written is tranfered from the writer to the reader,
423491
the fibre is removed from association with the channel,
424492
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.
425495
</p><p>When a read operation is performed on a channel by the running fibre,
426496
if there are fibres on the channel which are waiting to write
427497
then one is selected, the data to be written is transfered from the writer to the reader,
428498
fibre, the fibre is removed from association with the channel,
429499
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.
430502
</p><p>When a fibre commits suicide, it is removed as the running fibre.
431503
</p><p>When a new fibre is spawned, both the spawner and spawnee are made active.
432504
</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
447519
</p><p>In addition, I/O transfers always result in the reader proceeding,
448520
to give it a chance to actually fetch the data before the write
449521
might modify it.
450-
</p><h2 id='next_h'><img src='/share/src/web/images/minus.gif' id='next' onclick='toggle(this,"next_d")' alt='+'/> 1.1 next</h2><div id='next_d' style='display:block'>
522+
</p><h2 id='next_h'><img src='/share/src/web/images/minus.gif' id='next' onclick='toggle(this,"next_d")' alt='+'/> 2.1 next</h2><div id='next_d' style='display:block'>
451523
<p>stuff
452524
</p><p><pre class='flxbg'><span class="lineno" id=line1></span> blah
453525
</pre></p><p>stuff
454-
</p></div></div><h1 id='high_h'><img src='/share/src/web/images/minus.gif' id='high' onclick='toggle(this,"high_d")' alt='+'/> 2 high</h1><div id='high_d' style='display:block'>
526+
</p></div></div><h1 id='high_h'><img src='/share/src/web/images/minus.gif' id='high' onclick='toggle(this,"high_d")' alt='+'/> 3 high</h1><div id='high_d' style='display:block'>
455527
<p>blam
456-
</p><h2 id='med1_h'><img src='/share/src/web/images/minus.gif' id='med1' onclick='toggle(this,"med1_d")' alt='+'/> 2.1 med1</h2><div id='med1_d' style='display:block'>
528+
</p><h2 id='med1_h'><img src='/share/src/web/images/minus.gif' id='med1' onclick='toggle(this,"med1_d")' alt='+'/> 3.1 med1</h2><div id='med1_d' style='display:block'>
457529
<p>stuff
458530
stuff
459531
stuff
@@ -490,13 +562,13 @@ <h1 id='The_concept_of_fibration_h'><img src='/share/src/web/images/minus.gif' i
490562
stuff
491563
stuff
492564
stuff
493-
</p></div><h2 id='med2_h'><img src='/share/src/web/images/minus.gif' id='med2' onclick='toggle(this,"med2_d")' alt='+'/> 2.2 med2</h2><div id='med2_d' style='display:block'>
565+
</p></div><h2 id='med2_h'><img src='/share/src/web/images/minus.gif' id='med2' onclick='toggle(this,"med2_d")' alt='+'/> 3.2 med2</h2><div id='med2_d' style='display:block'>
494566
<p>stuff
495-
</p></div><h2 id='med3_h'><img src='/share/src/web/images/minus.gif' id='med3' onclick='toggle(this,"med3_d")' alt='+'/> 2.3 med3</h2><div id='med3_d' style='display:block'>
567+
</p></div><h2 id='med3_h'><img src='/share/src/web/images/minus.gif' id='med3' onclick='toggle(this,"med3_d")' alt='+'/> 3.3 med3</h2><div id='med3_d' style='display:block'>
496568
<p>stuff <em>inline html works</em>
497569
but we have <code>micros</code> for inline code as well.
498570
<a href= https://www.itkservices2.com/nem_review_1.2>See ITK stuff</a>
499-
</p><h3 id='low_h'><img src='/share/src/web/images/minus.gif' id='low' onclick='toggle(this,"low_d")' alt='+'/> 2.3.1 low</h3><div id='low_d' style='display:block'>
571+
</p><h3 id='low_h'><img src='/share/src/web/images/minus.gif' id='low' onclick='toggle(this,"low_d")' alt='+'/> 3.3.1 low</h3><div id='low_d' style='display:block'>
500572
<p>level 3 stuff
501573
</p><p><pre class='flxbg'><span class="lineno" id=line1></span> blah
502574
</pre></p><p>stuff

0 commit comments

Comments
 (0)