11 months ago |
37 |
1 |
#include <stdio.h> | ||
2 |
#include <stddef.h> | ||||
3 |
#include "coroutine.h" | ||||
4 |
#include "generator.h" | ||||
5 |
#include "asleep.h" | ||||
6 |
#include "task.h" | ||||
7 |
|||||
8 |
#include <dirent.h> | ||||
9 |
#include <string.h> | ||||
10 |
#include <stdlib.h> | ||||
11 |
#include <time.h> | ||||
Last month |
12 |
#include <assert.h> | |||
11 months ago |
37 |
13 |
|||
8 months ago |
14 |
#define DEMO_STACK_SIZE (8192*sizeof(void *)) | |||
11 months ago |
37 |
15 |
|||
16 |
void *chaindeeper(void *param){ | ||||
17 |
// enough headroom for printf on an Intel Mac - your system may be different | ||||
18 |
if (Coroutine_GetStackHeadroom() < 2000){ | ||||
8 months ago |
19 |
void *result; | |||
2 months ago |
20 |
bool fail = Coroutine_Chain(DEMO_STACK_SIZE, 0, chaindeeper, param, &result); | |||
8 months ago |
21 |
return fail ? NULL : result; | |||
11 months ago |
37 |
22 |
} | ||
10 months ago |
23 |
printf("%ld %ld\n", (long)param, Coroutine_GetStackHeadroom()); | |||
2 months ago |
24 |
bool domore = Generator_Yield(param); | |||
25 |
if (domore){ | ||||
26 |
long depth = (long)param; | ||||
27 |
if (depth > 1000){ | ||||
28 |
return NULL; | ||||
29 |
} | ||||
30 |
return chaindeeper((void *)(depth + 1)); | ||||
11 months ago |
37 |
31 |
} | ||
2 months ago |
32 |
return NULL; | |||
11 months ago |
37 |
33 |
} | ||
34 |
|||||
35 |
|||||
36 |
void *chaintest( | ||||
37 |
void *param | ||||
38 |
){ | ||||
39 |
(void)param; | ||||
40 |
|||||
2 months ago |
41 |
// Need to run two coroutines so that at least one of their stacks is limited, and so | |||
42 |
// needs to chain | ||||
43 |
Generator gen1; | ||||
44 |
Generator_ctor(&gen1, DEMO_STACK_SIZE, 0, chaindeeper, 0); | ||||
45 |
Generator gen2; | ||||
46 |
Generator_ctor(&gen2, DEMO_STACK_SIZE, 0, chaindeeper, 0); | ||||
47 |
void *param1; | ||||
48 |
void *param2; | ||||
49 |
while(Generator_Next(&gen1, ¶m1) && Generator_Next(&gen2, ¶m2)){ | ||||
50 |
} | ||||
51 |
Generator_dtor(&gen2); | ||||
52 |
Generator_dtor(&gen1); | ||||
53 |
|||||
6 months ago |
54 |
Coroutine_Report report = Coroutine_GetReport(); | |||
55 |
printf("%d routines using a pool of %d, min headroom %zu\n", report.coroutines_created, report.coroutines_pool_size, report.lowest_headroom); | ||||
11 months ago |
37 |
56 |
|||
57 |
return param; | ||||
58 |
} | ||||
59 |
|||||
Last month |
60 |
void on_yield(void *param){ | |||
61 |
(void)param; | ||||
62 |
} | ||||
11 months ago |
37 |
63 |
|||
Last month |
64 |
void *chaintest2_inner( | |||
65 |
void *param | ||||
66 |
){ | ||||
67 |
Coroutine *root = param; | ||||
68 |
Coroutine_Continue(root, NULL, true); | ||||
69 |
Coroutine_Yield((void *)456, on_yield, NULL); | ||||
70 |
assert(Coroutine_GetValue(root) == (void *)3); | ||||
71 |
return NULL; | ||||
72 |
} | ||||
73 |
|||||
74 |
void *chaintest2_outer( | ||||
75 |
void *param | ||||
76 |
){ | ||||
77 |
Coroutine *root = param; | ||||
78 |
assert(Coroutine_GetValue(root) == (void *)1); | ||||
79 |
Coroutine_Continue(root, NULL, true); | ||||
80 |
Coroutine_Yield((void *)123, on_yield, NULL); | ||||
81 |
assert(Coroutine_GetValue(root) == (void *)2); | ||||
82 |
Coroutine_Chain(DEMO_STACK_SIZE, 0, chaintest2_inner, root, NULL); | ||||
83 |
Coroutine_Continue(root, NULL, true); | ||||
84 |
return (void *)789; | ||||
85 |
} | ||||
86 |
|||||
87 |
// This test checks the function of chaining: | ||||
88 |
// * Yielding inside a chained coroutine stores the value with | ||||
89 |
// the outermost/root coroutine of the chain. | ||||
90 |
// * Continuing the root coroutine of a chain continues the chain | ||||
91 |
// tip coroutine (ie the one which had yielded last) | ||||
92 |
void *chaintest2( | ||||
93 |
void *param | ||||
94 |
){ | ||||
95 |
(void)param; | ||||
96 |
Coroutine *me = Coroutine_GetActive(); | ||||
97 |
Coroutine *cor = Coroutine_New(DEMO_STACK_SIZE, 0, chaintest2_outer); | ||||
98 |
|||||
99 |
Coroutine_Continue(cor, me, true); | ||||
100 |
Coroutine_Yield((void *)1, on_yield, NULL); | ||||
101 |
assert(Coroutine_IsRunning(cor)); | ||||
102 |
assert(Coroutine_GetValue(cor) == (void *)123); | ||||
103 |
|||||
104 |
Coroutine_Continue(cor, me, true); | ||||
105 |
Coroutine_Yield((void *)2, on_yield, NULL); | ||||
106 |
assert(Coroutine_IsRunning(cor)); | ||||
107 |
assert(Coroutine_GetValue(cor) == (void *)456); | ||||
108 |
|||||
109 |
Coroutine_Continue(cor, me, true); | ||||
110 |
Coroutine_Yield((void *)3, on_yield, NULL); | ||||
111 |
assert(!Coroutine_IsRunning(cor)); | ||||
112 |
assert(Coroutine_GetValue(cor) == (void *)789); | ||||
113 |
|||||
114 |
Coroutine_Delete(cor); | ||||
115 |
return NULL; | ||||
116 |
} | ||||
117 |
|||||
118 |
|||||
11 months ago |
37 |
119 |
int main(int argc, char *argv[]) { | ||
120 |
(void)argc; | ||||
121 |
(void)argv; | ||||
122 |
|||||
2 months ago |
123 |
Coroutine_Run(DEMO_STACK_SIZE, 0, chaintest, NULL, NULL); | |||
Last month |
124 |
Coroutine_Run(DEMO_STACK_SIZE, 0, chaintest2, NULL, NULL); | |||
11 months ago |
37 |
125 |
|||
6 months ago |
126 |
return 0; | |||
11 months ago |
37 |
127 |
} | ||
128 |