128 lines3.5 KB
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>
12#include <assert.h>
13
14#define DEMO_STACK_SIZE (8192*sizeof(void *))
15
16void *chaindeeper(void *param){
17 // enough headroom for printf on an Intel Mac - your system may be different
18 if (Coroutine_GetStackHeadroom() < 2000){
19 void *result;
20 bool fail = Coroutine_Chain(DEMO_STACK_SIZE, 0, chaindeeper, param, &result);
21 return fail ? NULL : result;
22 }
23 printf("%ld %ld\n", (long)param, Coroutine_GetStackHeadroom());
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));
31 }
32 return NULL;
33}
34
35
36void *chaintest(
37 void *param
38){
39 (void)param;
40
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, &param1) && Generator_Next(&gen2, &param2)){
50 }
51 Generator_dtor(&gen2);
52 Generator_dtor(&gen1);
53
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);
56
57 return param;
58}
59
60void on_yield(void *param){
61 (void)param;
62}
63
64void *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
74void *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)
92void *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
119int main(int argc, char *argv[]) {
120 (void)argc;
121 (void)argv;
122
123 Coroutine_Run(DEMO_STACK_SIZE, 0, chaintest, NULL, NULL);
124 Coroutine_Run(DEMO_STACK_SIZE, 0, chaintest2, NULL, NULL);
125
126 return 0;
127}
128