Skip to content

Commit 61edb00

Browse files
committed
landing page links
1 parent 9c5650b commit 61edb00

File tree

4 files changed

+134
-12
lines changed

4 files changed

+134
-12
lines changed

GNUmakefile

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
pretty:
2+
env DYLD_LIBRARY_PATH=${LD_LIBRARY_PATH} flx_pretty embedc.fdoc
3+
env DYLD_LIBRARY_PATH=${LD_LIBRARY_PATH} flx_pretty corout.fdoc
4+
5+
extract:
6+
flx_iscr embedc.fdoc
7+
flx_iscr corout.fdoc
8+
9+
10+
test:
11+
flx --regex='examples/.*\.flx'
12+
13+
deploy:
14+
git add examples/*/*.flx
15+
git commit -a
16+
git push
17+
18+
all: pretty extract test deploy
19+

corout.fdoc

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
@tangler ex2 = examples/ex2.flx
33
@tangler ex3 = examples/ex3.flx
44
@tangler ex4 = examples/ex4.flx
5+
@tangler ex5 = examples/ex5.flx
56
@title coroutines
67
@h1 A low level example.
78
I will show a simple low level example of coroutines, it will be a
@@ -315,6 +316,8 @@ the fibre is not technically dead because it no longer exists.
315316
A <em>channel</em> is an object associated with which
316317
set of fibres all waiting to read or all waiting to write.
317318

319+
@h2 Operations
320+
@h3 write
318321
When a write operation is performed on a channel by the running fibre,
319322
if there are fibres on the channel which are waiting to read
320323
then one is selected, the data to be written is tranfered from the writer to the reader,
@@ -323,6 +326,7 @@ and both the running and reader fibre are made active.
323326
Otherwise if there is no readers waiting on the channel, the writer is
324327
suspended and put on the channel.
325328

329+
@h3 read
326330
When a read operation is performed on a channel by the running fibre,
327331
if there are fibres on the channel which are waiting to write
328332
then one is selected, the data to be written is transfered from the writer to the reader,
@@ -331,25 +335,30 @@ and both the running and reader fibre are made active.
331335
Otherwise if there is no writers waiting on the channel, the writer is
332336
suspended and put on the channel.
333337

338+
@h3 suicide
334339
When a fibre commits suicide, it is removed as the running fibre.
335340

341+
@h3 spawn
336342
When a new fibre is spawned, both the spawner and spawnee are made active.
337343

344+
@h3 Scheduler operation
338345
When there is no running fibre, then if an active fibre exists,
339346
an active fibre is selected and promoted to running state
340347
and the thread of control begins executing it.
341348

342349
When there is no running fibre, and no active fibres,
343350
the whole system terminates. Any fibres waiting on I/O become dead
344351

352+
@h2 Communication Sequential Coroutines
345353
The description above is a complete account of the abstract semantics
346354
known as <em>Communicating Sequential Coroutines</em> or CSC, it is a
347355
sub system obtain from Tony Hoare's <em>Communicating Sequenmtial Processes</em>
348356
or CSP, in which concurrency is replaced by an indeterminate total ordering.
349357

350358
To be precise in CSC all events are totally ordered, however the exact ordering
351359
is not determinate. This is because a scheduler running the system is free
352-
to pick any active fibre to run when one is needed.
360+
to pick any active fibre to run when one is needed; similarly
361+
a read or write operation can match with any dual operation on a channel.
353362

354363
In the Felix implementation, a spawned fibre runs immediately
355364
if the @{spawn_fthread} procedure is used to launch it, or the
@@ -359,4 +368,42 @@ In addition, I/O transfers always result in the reader proceeding,
359368
to give it a chance to actually fetch the data before the write
360369
might modify it.
361370

371+
@h1 No Deadlocks
372+
Most threading systems can deadlock. Here is the classical situation:
373+
@tangle ex5
374+
chip D connector io pin inp: %<int pin out: %>int
375+
{
376+
while true do
377+
var x = read io.inp;
378+
write (io.out, x);
379+
done
380+
}
381+
device A = D;
382+
device B = D;
383+
circuit
384+
connect A.out, B.inp
385+
connect B.out, A.inp
386+
endcircuit
387+
println$ "Done";
388+
@
389+
Both devices start by reading, so there's nothing to read because
390+
neither can proceed to writing. So the system hangs, right!
391+
392+
Er .. NO! Both chips are suspended, the mainline completes,
393+
and the scheduler terminates the program because there is no work to do.
394+
395+
Let me repeat in bold letters:
396+
397+
<bf style="color:red">FELIX COROUTINES CANNOT DEADLOCK</bf>
398+
399+
However they can <em>livelock</em>, but only if you mismanage
400+
manual circuit construction. Here's an example:
401+
@tangle ex6
402+
var inp,out = mk_ioschannel_pair[int]();
403+
spawn_fthread { write (out, 42); };
404+
@
405+
406+
This is a livelock because the mainline <em>could</em> read
407+
the written data on the channel endpoint @{inp} but doesn't.
408+
362409

corout.html

Lines changed: 60 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,15 @@
316316
"Asynchronous I/O",
317317
"Felix is a coroutine",
318318
"Running subsystems",
319-
"The concept of fibration"
319+
"The concept of fibration",
320+
"Operations",
321+
"write",
322+
"read",
323+
"suicide",
324+
"spawn",
325+
"Scheduler operation",
326+
"Communication Sequential Coroutines",
327+
"No Deadlocks"
320328
];
321329
function expand_all(dummy)
322330
{
@@ -394,8 +402,13 @@
394402
</div>
395403
<div class=m1 onclick="mshow('menu4','#The concept of fibration_h')"> <a href="#The_concept_of_fibration_h">The concept of fibration</a></div>
396404
<div class=sm id=menu4>
405+
<div class=m2><a href="#Operations_h">Operations</a></div>
406+
<div class=m2><a href="#Communication_Sequential_Coroutines_h">Communication Sequential Coroutines</a></div>
397407
</div>
398-
<script>counter_max=4;</script>
408+
<div class=m1 onclick="mshow('menu5','#No Deadlocks_h')"> <a href="#No_Deadlocks_h">No Deadlocks</a></div>
409+
<div class=sm id=menu5>
410+
</div>
411+
<script>counter_max=5;</script>
399412
</div>
400413
<!--End Left Margin Toc-->
401414

@@ -681,40 +694,78 @@ <h1 id='A_low_level_example._h'><img src='/share/src/web/images/minus.gif' id='A
681694
the fibre is not technically dead because it no longer exists.
682695
</p><p>A <em>channel</em> is an object associated with which
683696
set of fibres all waiting to read or all waiting to write.
684-
</p><p>When a write operation is performed on a channel by the running fibre,
697+
</p><h2 id='Operations_h'><img src='/share/src/web/images/minus.gif' id='Operations' onclick='toggle(this,"Operations_d")' alt='+'/> 4.1 Operations</h2><div id='Operations_d' style='display:block'>
698+
<h3 id='write_h'><img src='/share/src/web/images/minus.gif' id='write' onclick='toggle(this,"write_d")' alt='+'/> 4.1.1 write</h3><div id='write_d' style='display:block'>
699+
<p>When a write operation is performed on a channel by the running fibre,
685700
if there are fibres on the channel which are waiting to read
686701
then one is selected, the data to be written is tranfered from the writer to the reader,
687702
the fibre is removed from association with the channel,
688703
and both the running and reader fibre are made active.
689704
Otherwise if there is no readers waiting on the channel, the writer is
690705
suspended and put on the channel.
691-
</p><p>When a read operation is performed on a channel by the running fibre,
706+
</p></div><h3 id='read_h'><img src='/share/src/web/images/minus.gif' id='read' onclick='toggle(this,"read_d")' alt='+'/> 4.1.2 read</h3><div id='read_d' style='display:block'>
707+
<p>When a read operation is performed on a channel by the running fibre,
692708
if there are fibres on the channel which are waiting to write
693709
then one is selected, the data to be written is transfered from the writer to the reader,
694710
fibre, the fibre is removed from association with the channel,
695711
and both the running and reader fibre are made active.
696712
Otherwise if there is no writers waiting on the channel, the writer is
697713
suspended and put on the channel.
698-
</p><p>When a fibre commits suicide, it is removed as the running fibre.
699-
</p><p>When a new fibre is spawned, both the spawner and spawnee are made active.
700-
</p><p>When there is no running fibre, then if an active fibre exists,
714+
</p></div><h3 id='suicide_h'><img src='/share/src/web/images/minus.gif' id='suicide' onclick='toggle(this,"suicide_d")' alt='+'/> 4.1.3 suicide</h3><div id='suicide_d' style='display:block'>
715+
<p>When a fibre commits suicide, it is removed as the running fibre.
716+
</p></div><h3 id='spawn_h'><img src='/share/src/web/images/minus.gif' id='spawn' onclick='toggle(this,"spawn_d")' alt='+'/> 4.1.4 spawn</h3><div id='spawn_d' style='display:block'>
717+
<p>When a new fibre is spawned, both the spawner and spawnee are made active.
718+
</p></div><h3 id='Scheduler_operation_h'><img src='/share/src/web/images/minus.gif' id='Scheduler operation' onclick='toggle(this,"Scheduler_operation_d")' alt='+'/> 4.1.5 Scheduler operation</h3><div id='Scheduler_operation_d' style='display:block'>
719+
<p>When there is no running fibre, then if an active fibre exists,
701720
an active fibre is selected and promoted to running state
702721
and the thread of control begins executing it.
703722
</p><p>When there is no running fibre, and no active fibres,
704723
the whole system terminates. Any fibres waiting on I/O become dead
705-
</p><p>The description above is a complete account of the abstract semantics
724+
</p></div></div><h2 id='Communication_Sequential_Coroutines_h'><img src='/share/src/web/images/minus.gif' id='Communication Sequential Coroutines' onclick='toggle(this,"Communication_Sequential_Coroutines_d")' alt='+'/> 4.2 Communication Sequential Coroutines</h2><div id='Communication_Sequential_Coroutines_d' style='display:block'>
725+
<p>The description above is a complete account of the abstract semantics
706726
known as <em>Communicating Sequential Coroutines</em> or CSC, it is a
707727
sub system obtain from Tony Hoare's <em>Communicating Sequenmtial Processes</em>
708728
or CSP, in which concurrency is replaced by an indeterminate total ordering.
709729
</p><p>To be precise in CSC all events are totally ordered, however the exact ordering
710730
is not determinate. This is because a scheduler running the system is free
711-
to pick any active fibre to run when one is needed.
731+
to pick any active fibre to run when one is needed; similarly
732+
a read or write operation can match with any dual operation on a channel.
712733
</p><p>In the Felix implementation, a spawned fibre runs immediately
713734
if the <code>spawn_fthread</code> procedure is used to launch it, or the
714735
running fibre continues instead, of <code>schedule_fthread</code> is used instead.
715736
</p><p>In addition, I/O transfers always result in the reader proceeding,
716737
to give it a chance to actually fetch the data before the write
717738
might modify it.
739+
</p></div></div><h1 id='No_Deadlocks_h'><img src='/share/src/web/images/minus.gif' id='No Deadlocks' onclick='toggle(this,"No_Deadlocks_d")' alt='+'/> 5 No Deadlocks</h1><div id='No_Deadlocks_d' style='display:block'>
740+
<p>Most threading systems can deadlock. Here is the classical situation:
741+
</p><pre class='inclusion'>
742+
examples/ex5.flx</pre>
743+
<p><pre class='flxbg'><span class="lineno" id=line1></span> <span class="big_keyword" title="defines a coroutine using chip idiom">chip</span> D <span class="small_keyword" title="the parameter of a chip">connector</span> io <span class="small_keyword" title="a field of the chip parameter">pin</span> inp: %&lt;<span class="library" title="binding of C int type">int</span> <span class="small_keyword" title="a field of the chip parameter">pin</span> out: %&gt;<span class="library" title="binding of C int type">int</span>
744+
<span class="lineno" id=line2></span> {
745+
<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>
746+
<span class="lineno" id=line4></span> <span class="big_keyword" title="Define a mutable variable">var</span> x = read io.inp;
747+
<span class="lineno" id=line5></span> <span class="library" title="Print a string to a stream">write</span> (io.out, x);
748+
<span class="lineno" id=line6></span> <span class="small_keyword" title="end of body">done</span>
749+
<span class="lineno" id=line7></span> }
750+
<span class="lineno" id=line8></span> <span class="small_keyword" title="a synonym for var to suit the chip idiom">device</span> A = D;
751+
<span class="lineno" id=line9></span> <span class="small_keyword" title="a synonym for var to suit the chip idiom">device</span> B = D;
752+
<span class="lineno" id=line10></span> <span class="small_keyword" title="defines the topology of chip connections">circuit</span>
753+
<span class="lineno" id=line11></span> <span class="small_keyword" title="connects two pins with a channel">connect</span> A.out, B.inp
754+
<span class="lineno" id=line12></span> <span class="small_keyword" title="connects two pins with a channel">connect</span> B.out, A.inp
755+
<span class="lineno" id=line13></span> <span class="small_keyword" title="defines the topology of chip connections">endcircuit</span>
756+
<span class="lineno" id=line14></span> <span class="library" title="Print a string to standard output with newline appended">println</span>$ <span class="fstring">"Done"</span>;
757+
</pre></p><p>Both devices start by reading, so there's nothing to read because
758+
neither can proceed to writing. So the system hangs, right!
759+
</p><p>Er .. NO! Both chips are suspended, the mainline completes,
760+
and the scheduler terminates the program because there is no work to do.
761+
</p><p>Let me repeat in bold letters:
762+
</p><p><bf style="color:red">FELIX COROUTINES CANNOT DEADLOCK</bf>
763+
</p><p>However they can <em>livelock</em>, but only if you mismanage
764+
manual circuit construction. Here's an example:
765+
</p><p><pre class="prefmtbg">var inp,out = mk_ioschannel_pair[int]();
766+
spawn_fthread { write (out, 42); };
767+
</pre></p><p>This is a livelock because the mainline <em>could</em> read
768+
the written data on the channel endpoint <code>inp</code> but doesn't.
718769
</p></div><!--Main Content Body End-->
719770

720771
</div> <!-- rightpanel contents end -->

index.html

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,13 +37,18 @@
3737
.caveat { background-color:#FF8080; color:black; }
3838
</style>
3939

40-
40+
<body>
4141
<h1>Felix programming system.</h1>
4242
<pre class='flxbg'>
4343
<span class="lineno" id=line1></span> <span class="library" title="Print a string to standard output with newline appended">println</span>$ <span class="fstring">"Hello World!"</span>;
4444
<span class="lineno" id=line2></span>
45-
4645
</pre>
4746

47+
<h2>Articles</h2>
48+
<ol>
49+
<li><a href=embedc.html>Embedding C/C++</a>
50+
<li><a href=corout.html>Coroutine Magic</a>
51+
</ol>
52+
</body>
4853
</html>
4954

0 commit comments

Comments
 (0)