1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
|
#include <stc/coroutine.h>
#include <stdio.h>
#include <stdint.h>
// Demonstrate to call another coroutine from a coroutine:
// First create prime generator, then call fibonacci sequence:
bool is_prime(long long i) {
for (long long j=2; j*j <= i; ++j)
if (i % j == 0) return false;
return true;
}
struct prime {
int count, idx;
long long result, pos;
int cco_state;
};
int prime(struct prime* g) {
cco_routine(g) {
if (g->result < 2) g->result = 2;
if (g->result == 2) {
if (g->count-- == 0) cco_return;
++g->idx;
cco_yield();
}
g->result += !(g->result & 1);
for (g->pos = g->result; g->count > 0; g->pos += 2) {
if (is_prime(g->pos)) {
--g->count;
++g->idx;
g->result = g->pos;
cco_yield();
}
}
cco_cleanup:
printf("final prm\n");
}
return 0;
}
// Use coroutine to create a fibonacci sequence generator:
struct fibonacci {
int count, idx;
long long result, b;
int cco_state;
};
int fibonacci(struct fibonacci* g) {
assert(g->count < 94);
long long sum;
cco_routine(g) {
g->idx = 0;
g->result = 0;
g->b = 1;
for (;;) {
if (g->count-- == 0)
cco_return;
if (++g->idx > 1) {
// NB! locals lasts only until next yield/await!
sum = g->result + g->b;
g->result = g->b;
g->b = sum;
}
cco_yield();
}
cco_cleanup:
printf("final fib\n");
}
return 0;
}
// Combine
struct combined {
struct prime prm;
struct fibonacci fib;
int cco_state;
};
int combined(struct combined* g) {
cco_routine(g) {
cco_await_call(prime(&g->prm));
cco_await_call(fibonacci(&g->fib));
// Reuse the g->prm context and extend the count:
g->prm.count = 8, g->prm.result += 2;
cco_reset(&g->prm);
cco_await_call(prime(&g->prm));
cco_cleanup:
puts("final combined");
}
return 0;
}
int main(void)
{
struct combined c = {.prm={.count=8}, .fib={14}};
int res;
cco_blocking_call(res = combined(&c)) {
if (res == CCO_YIELD)
printf("Prime(%d)=%lld, Fib(%d)=%lld\n",
c.prm.idx, c.prm.result,
c.fib.idx, c.fib.result);
}
}
|