A semi-coroutine asymmetrically reactivates the coroutine that previously activated it.
Output successive Fibonacci numbers on each call to routine
| 3 state | |
|---|---|
| C single instance | C∀ multiple instances |
#include <stdio.h> int fn1, fn2, |
#include <fstream.hfa> #include |
| 1 state, multiple instances | |
|---|---|
| C | C∀ |
#include <stdio.h>
typedef struct { int fn1, fn; } Fib;
#define FibCtor { 0, 1 }
int fib( Fib * f ) {
int ret = f->fn1;
f->fn1 = f->fn;
f->fn = f->fn + fn;
return ret;
}
int main() {
Fib f1 = FibCtor, f2 = FibCtor;
for ( int i = 0; i < 10; i += 1 ) {
printf( "%d %d\n", fib( &f1 ), fib( &f2 ) );
}
}
|
#include <fstream.hfa> #include |
Input successive characters on each call to routine
| C | C∀ |
|---|---|
#include <stdio.h>
struct Format {
char ch;
int g, b;
};
void format( struct Format * fmt ) {
if ( fmt->ch != -1 ) { // not EOF ?
printf( "%c", fmt->ch );
fmt->b += 1;
if ( fmt->b == 4 ) { // block ?
printf( " " ); // separator
fmt->b = 0;
fmt->g += 1;
}
if ( fmt->g == 5 ) { // group ?
printf( "\n" ); // separator
fmt->g = 0;
}
} else {
if ( fmt->g != 0 || fmt->b != 0 ) printf( "\n" );
}
}
int main() {
struct Format fmt = { 0, 0, 0 };
for () {
scanf( "%c", &fmt.ch );
if ( feof( stdin ) ) break;
format( &fmt );
}
fmt.ch = -1;
format( &fmt );
}
|
#include <fstream.hfa> #include |
Input successive characters on each call to routine
// network protocol: ... STX ... message ... ESC ETX ... message ... ETX 2-byte CRC ... #include <fstream.hfa> #include<coroutine.hfa> enum Status { CONT, MSG, ESTX, ELNTH, ECRC };coroutine Driver { Status status; char * msg, byte; }; void ?{}( Driver & d, char * m ) { d.msg = m; } Status next( Driver & d, char b ) with( d ) { byte = b;resume( d ); return status; } void checkCRC( Driver & d, unsigned int sum ) with( d ) {suspend; unsigned short int crc = byte << 8; // sign extension over writtensuspend; // prevent sign extension for signed char status = (crc | (unsigned char)byte) == sum ? MSG : ECRC; } void main( Driver & d ) with( d ) { enum { STX = '\002', ESC = '\033', ETX = '\003', MaxMsg = 64 }; msg: for () { // parse message status = CONT; unsigned int lnth = 0, sum = 0; while ( byte != STX ) suspend; emsg: for () {suspend; choose ( byte ) { // process byte case STX: status = ESTX; suspend; continue msg; case ETX: break emsg; case ESC:suspend; } if ( lnth >= MaxMsg ) { // buffer full ? status = ELNTH; suspend; continue msg; } msg[lnth++] = byte; sum += byte; } msg[lnth] = '\0'; // terminate string checkCRC( d, sum ); // refactor CRC checksuspend; } } int main() { char msg[65], byte; Driver driver = { msg }; try { for () { // read until end of file sin | byte; // read one character choose( next( driver, byte ) ) { // analyse character case MSG: sout | "msg:" | msg; case ESTX: sout | "STX in message"; case ELNTH: sout | "message too long"; case ECRC: sout | "CRC failure"; default: ; } } } catch( end_of_file * ) { // end-of-file raised } }
A full-coroutine symmetrically activates another coroutine, which directly or indirectly reactivates the original coroutine (activation cycle).
Resume-resume cycle between coroutines
#include <fstream.hfa> #include<coroutine.hfa> coroutine PingPong { const char * name; unsigned int N; PingPong & part; }; void ?{}( PingPong & this, const char * name, unsigned int N, PingPong & part ) { this.[name, N] = [name, N]; &this.part = ∂ } void ?{}( PingPong & this, const char * name, unsigned int N ) { this{ name, N, *0p }; // call first constructor } void cycle( PingPong & pingpong ) {resume( pingpong ); } void partner( PingPong & this, PingPong & part ) { &this.part = ∂resume( this ); } void main( PingPong & pingpong ) with(pingpong) { // ping's starter ::main, pong's starter ping for ( N ) { // N ping-pongs sout | name; cycle( part ); } } int main() { enum { N = 20 }; PingPong ping = { "ping", N }, pong = { "pong", N, ping }; partner( ping, pong ); }
Resume-resume cycle between coroutines
#include <fstream.hfa> #include |
|