1280 lines39.8 KB
1Stackful coroutines in C.
2
3* `Task` & `Future` coroutines which can pause, waiting for a future.
4* `ASleep` an example of pausing `Task`s using `Future`s.
5* `Generator` coroutines used as generators for loops.
6* `Coroutine` the base coroutine engine.
7
8Your code doesn't need to do anything special to be a coroutine. Only standard, or commonly available libraries are needed.
9
10## Quick Start
11
12### Installing
13
14You will need to build & link the code, `coroutine/*.c`, as part of your project, and ensure the headers, `include/*`, are available on your include path.
15
16### Tasks
17
18To run `Task`s:
19
20 #!C
21 #include "coroutine.h"
22 #include "task.h"
23 main(){
24 size_t min_stack_size = 8192 * sizeof(void *);
25 void *res = NULL;
26 bool canceled = Task_Run(min_stack_size, 0, maintask, &param, &res);
27 }
28
29`Task_Run` runs tasks, switching between them when the current task waits on an `Future`. `maintask()` is run as a task. The start function for any task looks like this:
30
31 #!C
32 bool mytask(void *param, void **res){
33
34 // do your thing here
35
36 return canceled;
37 }
38
39When `Task` returns from its start function, it returns whether it was canceled. Canceled `Task`s are assumed to have not finished what they were doing.
40
41Within your main task, create `Task`s and `Task_Await()` them when you want to wait for their result:
42
43 #!C
44 Task task1;
45 Task_ctor(&task1, min_stack_size, 0, adifferenttask, &task1param);
46
47 void *result;
48 bool canceled = Task_Await(&task1, &result);
49
50 Task_dtor(&task1);
51
52 // use the result
53
54When a task needs to wait for something, and wants to allow other tasks to run, it should use a `Future`:
55
56 #!C
57 Future future;
58 Future_ctor(&future);
59
60 // pass the future to the background-thing-which-might-take-a-while
61
62 void *res;
63 bool canceled = Future_Await(&future, &res);
64
65 Future_dtor(&future);
66
67When the background-thing-which-might-take-a-while has a result:
68
69 #!C
70 Future_SetResult(future, false, result);
71
72### ASleep
73
74`ASleep()` needs its own system to be started to work:
75
76 #!C
77 ASleep_StartSystem()
78 // Run tasks here which may now use ASLeep()
79 ASleep_StopSystem();
80
81Note that `ASleep_StartSystem()` / `ASleep_StopSystem()` is only needed once per process.
82
83Sleeping in a task:
84
85 #!C
86 bool mytask(void *param, void **result){
87 ..
88 ASleep(time_to_sleep);
89 ..
90 }
91
92### Generators
93
94Your code needs to be in a `Coroutine` to use a `Generator`:
95
96 #!C
97 void *mycoroutine(void *param){
98 // You can use a Generator here
99 }
100
101 Coroutine_Run(StackSpace, 0, mycoroutine, NULL, NULL);
102
103You will need a generator function:
104
105 #!C
106 void *yield_my_things(void *param){
107 bool domore = true;
108
109 // loop/call functions to find more values to yield, and when you have one:
110 domore = Generator_Yield(thing);
111 // .. if domore is false, exit your generator - it is being destructed
112
113 // not actually used by generators, but this is a useful convention for bubbling
114 // the flag out to calling functions.
115 return (void *)domore;
116 }
117
118And to use it:
119
120 #!C
121 Generator gen;
122 Generator_ctor(&gen, generator_stack_size, yield_my_things, "..");
123 void *thing;
124 while(Generator_Next(&gen, &thing)){
125 // use thing - a value yielded by your generator
126 }
127 Generator_dtor(&gen);
128
129### Coroutines
130
131While you can use coroutines directly, it's designed as a system to support more useful patterns, like `Async` and `Generators`.
132
133Your coroutine will need to have a start function:
134
135 #!C
136 void *start(void *param){
137 ...
138 }
139
140When there is no coroutine running, start your 'main' coroutine:
141
142 #!C
143 if (Coroutine_Run(min_stack_size, min_stack_headroom, comain, param, &result)){
144 // handle the failure
145 }
146
147Create other coroutines like this:
148
149 #!C
150 Coroutine *cor = Coroutine_New(min)stack_size, min_stack_headroom, start);
151
152When you want a Coroutine to be queued to run:
153
154 #!C
155 Coroutine_Continue(cor, value, run_early);
156
157`value` will be start function's parameter, or the value returned from the yield.
158
159Within the Coroutine, to yield a value, and allow other `Coroutine`s to run:
160
161 #!C
162 void *Coroutine_Yield(value, on_yield, void *me);
163
164The on_yield function is called after the coroutine has been 'wait'ed, but before the next coroutine is resumed.
165
166## Prerequisites
167
168These libraries rely on as much as possible on C's cross-platform comfort zone. C's standard libraries are used as far as possible, but, as `threads.h` is not usually supported, but `pthread.h` usually is, `pthread.h` has been used.
169
170If your system isn't supported directly by coroutine, you should be able to configure it in `cor_platform.c`, `cor_platform.h` and `cor_platform_inc.h`.
171
172## How it Works
173
174When you `Coroutine_RunSystem()` the passed-in callback is called within a Coroutine and the stack is now managed by the Coroutine system.
175
176The coroutine system divides the C stack into smaller stacks, using one of these smaller stacks for each coroutine. This limits the total stack space for all your coroutines - you may need to consider the stack size of each of your coroutines, and also whether a larger C stack might be needed.
177
178Each of your threads has its own stack - the coroutine system can be run, or not, independantly on each thread. For some special cases, you may want to adjust each of your thread's stack sizes depending on how it is used.
179
180The C stack memory is managed similarly to a malloc heap. Coroutine stacks are allocated on a first-fit basis, and merged on free. When a coroutine runs, if there's free stack beyond the requested limits, that is added in.
181
182When not running:
183
184 ...|[used stack][unused stack ]| free |...
185
186When running:
187
188 ...|[used stack][unused stack ]|...
189
190This means the function called back by `Coroutine_RunSystem()` will have all the stack, and be a Coroutine itself.
191
192When your coroutine yields and during `Coroutine_New()`, its stack is trimmed back so that there is free stack to allocate more Coroutines:
193
194when running:
195
196 ...|[used stack][unused stack ]|...
197
198When yielded and during `Coroutine_New()`:
199
200 ...|[used stack][unused stack ]|free |...
201
202the two stack size parameters set how much the stack is trimmed back:
203
204 ...|[used stack][unused stack ]|...
205 ...|<----min_size--------------->|...
206
207When trimmed:
208
209 ...|[used stack][unused stack ]|free |...
210 ...|<----min_size--------------->|...
211
212and
213
214 ...|[used stack][unused stack ]|...
215 <-min_headroom->
216
217When trimmed:
218
219 ...|[used stack][unused stac ]|free |...
220 <-min_headroom->
221
222If you want to run your coroutine with a fixed amount of stack, start your coroutine like this:
223
224 Coroutine_New(stack_size, 0, entry)
225
226If you want to monitor your coroutine's stack's headroom and chain as necessary:
227
228 Coroutine_New(0, headroom_size, entry)
229
230## Style
231
232The style is influenced by C++. For example, where possible, a `Something *Something_New(a, b, c)` and `Something_Delete(Something *)` will have corresponding `Somthing_ctor(Somthing *, a, b, c)` and `Something_dtor(Something *)` to initialise and finalise a `Something` on the stack, or within another object. Using `.._ctor()` and `.._dtor()` will be faster as they avoid the `malloc()` and `free()`.
233
234 #!C
235 Something *oneofthem = Something_New();
236 // use oneofthem
237 Something_Delete(oneofthem);
238
239Can be also be done like this, and this will run faster:
240
241 #!C
242 Something oneofthem;
243 Something_ctor(&oneofthem);
244 // use oneofthem
245 Something_dtor(&oneofthem);
246
247The exception is `Coroutine_New()` and `Coroutine_Delete()`. The returned `Coroutine` is somewhere on your thread's stack - its memory is managed by the coroutine system, and is allocated and freed quickly.
248
249## Usage
250
251When you are using coroutines or generators:
252
253 #!C
254 void *myfunc(void *){
255 // your function here
256 }
257
258 size_t min_size = 8192 * sizeof(void *);
259 size_t min_headroom = 256 * sizeof(void *);
260 if (Coroutine_Run(min_size, min_headroom, myfunc, (void *)myparam, NULL)){
261 // handle the failure
262 }
263
264You can make many calls to `Coroutine_Run()` or `Task_Run()`. `Coroutine_Run()` ensures the system is started, and that `myfunc` is called
265from inside a Coroutine. In paeticular, if the Coroutine system is running and `Coroutine_Run()` is called from inside a coroutine, then `myfunc` is simply called.
266
267## Stack Overruns
268
269The C stack is divided into smaller stacks. There's one, the startup stack, to give some room for `start` in `Coroutine_RunSystem` to work, and then each `Coroutine` has its own stack. These have guard markers which are checked to see if the stack has overrun. If there is a stack overrun, the system cannot continue - a message is output and the programe exited. There's a number of ways to avoid this issue:
270
271* Use less stack. This is, sometimes, the right advice, especially if the startup stack overruns. The expectation is that very little is done by `start` in `Coroutine_RunSystem`. If your situation needs more doing, you can...
272
273* increase the stack size for your `Coroutine`. If your use case is even more demanding, such as if you want 1000s of coroutines (so you need small stack chunks), /and/ some of them can recurse an unknown amount (so you need a deep stack for that `Coroutine`), then you can...
274
275* monitor stack headroom, and add another stack chunk if you need to:
276
277In this last case you'll need to add some code at key points:
278
279 #!C
280 void *myfunction(void *param){
281 if (Coroutine_GetStackHeadroom() < MIN_ALLOWED_STACK){
282 void *result;
283 Coroutine_Err err = Coroutine_Chain(min_stack_size, min_stack_headroom, myfunction, param, &result);
284 if (err){
285 // handle failure
286 }
287 return result;
288 }
289 // do everything normally
290 }
291
292More realistically:
293
294 #!C
295 struct myfunctionparams {
296 int a;
297 char *b;
298 struct dog *d;
299 }
300
301 void *mychain(void *param){
302 struct myfunctionparams *myparams = (struct myfunctionparams *)params;
303 return (void *)myfunction(myparams->a, myparams->b, *myparams->d);
304 }
305
306 int myfunction(int a, char *b, struct dog d){
307 if (Coroutine_GetStackHeadroom() < MIN_ALLOWED_STACK){
308 struct myfunctionparams params = {
309 a,
310 b,
311 &d
312 };
313 void *result;
314 Coroutine_Err err = Coroutine_Chain(my_stack_size, mychain, &params, &result);
315 if (err){
316 // handle failure
317 }
318 return (int)(intptr_t)result;
319 }
320 }
321
322And if you want to panic if the C stack overruns:
323
324 #!C
325 if (Coroutine_GetStackHeadroom() < MIN_ALLOWED_COROUTINE_STACK){
326 if (Coroutine_HasCoroutinesInFreePool() ||
327 (char *)Coroutine_GetCStackTop() - c_stack_end >= MIN_ALLOWED_C_STACK) {
328 struct myfunctionparams params = {
329 a,
330 b,
331 &d
332 };
333 void *result;
334 if (Coroutine_Chain(my_stack_size, mychain, &params, &result)){
335 // handle failure
336 }
337 return (int)(intptr_t)result;
338 }
339 // panic now
340 }
341
342## Configuring for Your Use Case
343
344There's a number of adjustments which you may need to make for your situation. These are, mostly, in `cor_platform.h` and `cor_platform_inc.h`.
345
346There's some options in `coroutine.h` which you may need to adjust:
347
348COROUTINE_STARTUP_STACK_SIZE
349: The amount of stack set aside for `start` in `Coroutine_RunSystem()`.
350
351COROUTINE_MINIMUM_STACK_SIZE
352: The minimum stack size you'll ask for. The C stack is managed as a heap. If one of the free blocks in that
353heap is big enough for your new Coroutine, and has spare, if that spare is too small for a `Coroutine` wanting
354`COROUTINE_MINIMUM_STACK_SIZE` of stack, then the whole free block is given to your new Coroutine, instead
355of being split into two.
356
357COROUTINE_GUARD_AT_C_STACK_LIMIT
358: Whether a guard pattern is written at the C stack's limit. Most OSs allow writing at the limit of the
359C stack. Windows does not. This flag controls whether a guard pattern is written at the C stack's limit.
360
361Aside: the author's best guess is that Windows assumes a write to the stack beyond the stack
362pointer is probably a bug, so when it detects reads & writes to unassigned memory pages in the stack area
363it checks whether the access is beyond the stack pointer. If it isn't, Windows assigns a page and the write
364continues as normal, if it is beyond the stack pointer, Windows generates a memory fault.
365
366`cor_platform.h` has customisations for your particular use case.
367
368_Cor_thread_local
369: How to declare a variable to be thread local
370
371COROUTINE_HAVE_ALLOCA_H
372: Whether your system can `#incude <alloca.h>`.
373
374_Cor_Mutex and related routines
375: Your system's mutex.
376
377_Cor_Realtime_Now
378: Return a realtime clock value compatible with _Cor_Semaphore_Wait.
379
380_Cor_Semaphore and related routines
381: Semaphores on your system.
382
383_Cor_Thread and related routines
384: Threads on your system.
385
386`coroutine_names_def.h` and `coroutine_names_undef.h` allows your installation to rename the
387coroutine functions. These headers exist so that code within Coroutine can use the functions'
388normal name, eg `Coroutine_New`, and allow your installation to use a different name, eg `Py_Coroutine_New`.
389
390#define Coroutine_NS(name)
391: Adjust this to set your installation's naming convention.
392
393Coroutine_API_FUNC(TYPE)
394: This allows tagging of functions to be accessible to loaded dlls.
395
396# API
397
398## Task & Future
399
400The pattern for using async is:
401
402 #!C
403 bool mymaintask(void *param, void **result){
404 // do your main task things here, like starting more tasks
405 }
406
407 void *res = NULL;
408 bool canceled = Task_Run(mymaintask, NULL, &res);
409
410To create and wait for a task:
411
412 #!C
413 Task task1;
414 Task_ctor(&task1, min_stack, min_stack_headorom, asynctask1, &task1param);
415 void *res = NULL;
416 bool canceled = Task_Await(&task1, void **res)
417 Task_dtor(&task1);
418
419or, if you prefer new & delete:
420
421 #!C
422 Task *task1 = Task_New(min_stack, min_stack_headorom, asynctask1, &task1param);
423 void *res = NULL;
424 bool canceled = Task_Await(task1, void **res)
425 Task_Delete(task1);
426
427Inside your task, when there is something to wait for and you want other tasks to run while your task is waiting, you will need a future:
428
429 #!C
430 Future future;
431 Future_ctor(&future);
432
433 // keep &future to hand for when the background thing completes
434 bool canceled = Future_Await(&future, NULL);
435
436 Future_dtor(&future);
437
438`Future_New()` and `Future_Delete()` are also available if you prefer that style.
439
440Inside the callback when the background thing is complete:
441
442 #!C
443 // result is a void *
444 Future_SetResult(future, result, false);
445
446or, if something went wrong:
447
448 #!C
449 // exception is a void *
450 Future_SetResult(future, exception, true);
451
452Back in the task, you can respond to the future:
453
454 #!C
455 ... Future_Await has returned
456 if (canceled){
457 // exit quickly - you've been canceled
458 // you could, for example, use the future's result as an exception, or error code here
459 }
460 // carry on - the future's result may be an actual result, that's up to you
461
462
463##### void Future_ctor(Future *fut)
464
465fut
466: The `Future` being constructed
467
468Initialise a future. When you no longer need it, use `Future_dtor()`.
469
470##### Future *Future_New()
471
472(returns)
473: The new future
474
475Allocates and initialises a future, When you no longer need it, use `Future_Delete()`.
476
477##### void Future_dtor(Future *fut)
478
479fut
480: The `Future` being destructed
481
482Destruct a future previously constructed with `Future_ctor()`.
483
484##### void Future_Delete(Future *fut)
485
486fut
487: The `Future` to be destructed and freed
488
489Delete (finalise and free) a future previously new'ed with `Future_New()`
490
491##### void Future_SetResult(Future *fut, bool canceled, void *value)
492
493fut
494: The `Future` whose result is being set
495
496canceled
497: The future's `canceled` setting
498
499value
500: The future's result `value`
501
502Set the result of a future. This has an effect only the first time its done, ie a completed future can't be canceled and a canceled future can't be completed. When an `Future` has a result, its watchers are called back.
503
504The `value` of a future might be a result if the future completes (when `canceled == false`), or could be some sort of exception value if `canceled == true`. The interpretation of a future's `value` is up to the user - as far as the async system is concerned, it's only a `void *`.
505
506##### bool Future_GetResult(Future *fut, void **res)
507
508(returns)
509: The `canceled` value of the `Future`.
510
511res
512: Where to store the value of the `Future`. This may be `NULL`.
513
514Get the result of a future.
515
516##### typedef void (*Future_Watcher)(void *me, Future *fut)
517
518A `Future_Watcher` is a callback called when a future has a result. The `me` parameter is the one passed to `Future_AddWatcher()`. `fut` is the future which has just got its result.
519
520##### void Future_AddWatcher(Future *fut, Future_Watcher watcher, void *me)
521
522fut
523: the `Future` to add a watcher to
524
525watcher
526: the callback to call when the `Future` has a result.
527
528me
529: the `me` value to pass to `watcher` when it is called back.
530
531Add a watcher (callback) to be called when the future has a result. If the future is already complete, `watcher` is immediately called. The `me` value is passed to the watcher as its `me` parameter. It is assumed that a watcher, identified by the `(watcher, me)` pair, will only be added once.
532
533##### void Future_RemoveWatcher(Future *fut, Future_Watcher watcher, void *me)
534
535fut
536: the `Future` to remove a watcher from
537
538watcher
539: the callback of the watcher to remove.
540
541me
542: the `me` value of the watcher to remove.
543
544Remove a watcher from a future. It is not an error if no watcher matching `(watcher, me)` is found - it has probably already been called back.
545
546##### bool Future_Await(Future *fut, void **res)
547
548(returns)
549: whether the `Future` was canceled.
550
551fut
552: The `Future` to wait for.
553
554res
555: Where to store the `value` of the future when it is has a result. May be `NULL`.
556
557The current `Task` is paused until the `Future` has a result. Other `Task`s are run while this one is waiting.
558
559##### typedef bool (*Task_Entry)(void *param, void **res)
560
561The entry function to an `Task`.
562
563##### void Task_ctor(Task *tsk, size_t min_stack, size_t min_stack_headroom, Task_Entry entry, void *param)
564
565tsk
566: The task to construct.
567
568min_stack
569: The minimum stack to keep for this task.
570
571min_stack_headroom
572: The minimum stack headroom to keep for this task.
573
574entry
575: The entry function for the task.
576
577param
578: The value for `param` to pass to `entry`.
579
580Initialises an `Task`. When you have finished with an `Task` you must finalise it using `Task_dtor()`
581
582 #!C
583 Task tsk;
584 Task_ctor(&tsk, mytask, myparam);
585 // tsk will run if you wait for a task or future
586 Task_Await(&tsk, NULL);
587 Task_dtor(&tsk);
588
589##### Task *Task_New(size_t min_stack, size_t min_stack_headroom, Task_Entry entry, void *param)
590
591(returns)
592: The new `Task`.
593
594min_stack
595: The minimum stack to keep for this task.
596
597min_stack_headroom
598: The minimum stack headroom to keep for this task.
599
600entry
601: The entry function for the task.
602
603param
604: The value for `param` to pass to `entry`.
605
606This allocates and initialises a new `Task`. When you have finished with your task, you must `Task_Delete()` it.
607
608 #!C
609 Task *tsk = Task_New(mytask, myparam);
610 // tsk will run if you wait for a task or future
611 Task_Await(tsk, NULL);
612 Task_Delete(tsk);
613
614##### void Task_dtor(Task *tsk)
615
616tsk
617: The `Task` to destruct.
618
619This finalises an `Task` you ealier initalised with `Task_ctor()`. It is an error to attempt to destruct a task which is running.
620
621 #!C
622 Task tsk;
623 Task_ctor(&tsk, mytask, myparam);
624 // use tsk
625 Task_dtor(&tsk);
626
627##### void Task_Delete(Task *tsk)
628
629tsk
630: The `Task` to delete.
631
632This finalises and frees an `Task` you ealier new'ed with `Task_New()`. It is an error to attempt to delete a task which is running.
633
634 #!C
635 Task *tsk = Task_New(mytask, myparam);
636 // use tsk
637 Task_Delete(tsk);
638
639##### static inline bool Task_Await(Task *tsk, void **res)
640
641(returns)
642: Whether the task was canceled.
643
644tsk
645: The `Task` to wait for.
646
647res
648: Where to store the `Task`'s value when it finishes. This may be NULL.
649
650The current `Task` waits for `tsk` to finish, and returns the result.
651
652##### void Task_Cancel(Task *tsk, void *cancel_value)
653
654tsk
655: The task to cancel.
656
657cancel_value
658: The value to set on any future this task waits on.
659
660This marks a task as canceled. When that task waits on a future that future will be canceled too, using `cancel_value`.
661
662##### static inline bool Task_IsCanceled(Task *tsk)
663
664(returns)
665: Whether the task is canceled.
666
667tsk
668: The task to get its canceled setting from.
669
670##### static inline Future *Task_GetAwaitedFuture(Task *tsk)
671
672(returns)
673: The future the task is waiting on. May be NULL.
674
675tsk
676: Teh task to read the future it is waiting on.
677
678Return the future a task is waiting on.
679
680##### bool Task_Run(Task_Entry start, void *value, void **res)
681
682(returns)
683: Whether `start` was canceled.
684
685start
686: The function to use as the main task.
687
688value
689: The value to pass to `start`.
690
691res
692: Where to store the result of `start`.
693
694Runs `start` as an `Task`. When `start` returns all other tasks must have been destructed, using `Task_dtor()` or `Task_Delete()`.
695
696## ASleep
697
698##### void ASleep_StartSystem()
699
700You must start the `ASleep` system to use it. This needs to happen per process. Once you've finished with `ASleep` you must `ASleep_StopSystem()`.
701
702 #!C
703 ASleep_StartSystem();
704 // Now you can use ASleep() on any thread
705 ASleep_StopSystem();
706
707##### void ASleep_StopSystem()
708
709Call this to stop the `ASleep` system.
710
711##### bool ASleep(float delay, void **value)
712
713(returns)
714: Whether the task was canceled.
715
716delay
717: How many seconds to delay for.
718
719value
720: Where to store the cancellation value. This may be NULL.
721
722Sleep for `delay` seconds. `*value` will be set to `NULL` if the sleep is successful, and the `cancel_value` if the task is canceled.
723
724## Generator
725
726The pattern for a `Generator` is:
727
728#### A loop which uses the `Generator
729
730 #!C
731 Generator gen;
732 Generator_ctor(&gen, min_stack, min_stack_headroom, mygen, &param);
733
734 void *value;
735 while(Generator_Next(&gen, &value)){
736 // use value here
737 }
738 // value is now the return value from the Generator
739
740 Generator_dtor(&gen);
741
742Or:
743
744 #!C
745 Generator *gen = Generator_New(min_stack, min_stack_headroom, mygen, &param);
746
747 void *value;
748 while(Generator_Next(gen, &value)){
749 // use value here
750 }
751
752 Generator_Delete(gen);
753
754`Generator`s yield a series of `void *`s - what the `void *`s mean is up to you. `Generator_Next()` returns a `bool` to indicate whether the `Generator` has finished.
755The `generator_stack_size` is the stack amount made available to your generator.
756
757#### A generator function
758
759 #!C
760 void *mygen(void *param){
761 bool domore = true;
762 // The parameter is a pointer to a string of chars
763 for (char *str = param; *str; ++str) {
764 // The value yielded is a pointer to a character in the string
765 domore = Generator_Yield(str);
766 if (!domore){
767 break;
768 }
769 }
770
771 return (void *)domore;
772 }
773
774The `bool` returned from `Generator_Yield()` indicates whether the generator function should yield more values. When it is `false` the `Generator` is being finalised - your generator function should close files, and release any other resources it has claimed, before exiting.
775
776##### void Generator_ctor(Generator *gen, size_t min_stack, size_t min_stack_headroom, void *(*start)(void *), void *param)
777
778gen
779: The `Generator` to construct.
780
781min_stack
782: The minimum amount of stack to keep for this generator.
783
784min_stack_headroom
785: The minimum stack headroom to keep for this generator
786
787start
788: The function which is the start/entry-point of the `Generator`.
789
790param
791: The value to pass to `start`.
792
793Initialise a `Generator`. When you no longer need the `Generator`, use `Generator_dtor()` to destruct it.
794
795 #!C
796 Generator gen;
797 Generator_ctor(&gen, min_stack, min_stack_headroom, mystart, &params);
798
799 // Generator is used
800
801 // ... later:
802 Generator_dtor(&gen);
803
804##### Generator *Generator_New(size_t min_stack, size_t min_stack_headroom, void *(*start)(void *), void *param)
805
806min_stack
807: The minimum amount of stack to keep for the generator.
808
809min_stack_headroom
810: The amount of stack headroom to keep for the generator.
811
812start
813: The function which is the start/entry-point of the `Generator`.
814
815param
816: The value to pass to `start`.
817
818`new` a `Generator` - malloc, and initialise it. When you no longer need the `Generator` use `Generator_dtor` to finalise it.
819
820 #!C
821 Generator *gen = Generator_New(my_stack, my_stack_headroom, mystart, &params);
822
823 // Generator is used
824
825 // ... later:
826 Generator_Delete(gen);
827
828##### void Generator_dtor(Generator *gen)
829
830gen
831: The `Generator` to destruct.
832
833Finalise a `Generator`. Once a `Generator` is no longer needed, it must be finalised:
834
835 #!C
836 // earlier...
837 Generator gen;
838 Generator_ctor(&gen, my_stack, my_stack_headroom, mystart, &params);
839
840 // Generator is used
841
842 // the Generator is no longer needed
843 Generator_dtor(&gen);
844
845
846##### void Generator_Delete(Generator *gen)
847
848gen
849: The `Generator` to delete.
850
851Finalise then `free()` a `Generator`. Once a `new`ed `Generator` is no longer needed, it must be deleted:
852
853 #!C
854 // earlier...
855 Generator *gen = Generator_New(mystart, &params);
856
857 // Generator is used
858
859 // the Generator is no longer needed
860 Generator_Delete(gen);
861
862
863##### bool Generator_Next(Generator *gen, void **value)
864
865(returns)
866: Whether there is a next value. `true` - there is a next value; `false` - the `Generator` has finished
867
868gen
869: The `Generator` to get the next value from.
870
871value
872: Where to store the next value.
873
874Get the next value yielded by the `Generator`.
875
876 #!C
877 void *value;
878 while(Generator_Next(gen, &value)){
879 // use value here
880 }
881
882The `Generator` feeds values to its client using `Generator_Yield()` - it is these values which `Generator_Next()` sets, in the example, `value` to.
883
884 When a `Generator` is finished it returns from `start`. When you call `Generator_Yield()` on a finished `Generator` it returns `false` and `value` will be the return value from `start`.
885
886##### bool Generator_Yield(void *value)
887
888(returns)
889: Whether the `Generator` should do more.
890
891value
892: The `Generator`'s next value.
893
894Yield a value from a `Generator`.
895
896 #!C
897 bool domore = Generator_Yield(value);
898
899`value` is then provided by `Generator_Next()` as the next value from the generator.
900
901The `bool` returned by `Generator_Yield()` says whether more values should be provided by your generator function. `true` - provide more values if there are any. `false` - close files, free memory, free up any other resources and `return`. `false` is returned when the `Generator` is being finalised before it has finished, ie the client has exited its `for`-loop early.
902
903## Coroutine
904
905##### Coroutine_Err
906
907The enum of errors:
908
909Coroutine_OK
910: Everything is OK. This is 0
911
912Coroutine_Err_SystemNotRunning
913: A `Coroutine` must be running to do this
914
915Coroutine_Err_SystemRunning
916: The `Coroutine` system must not be running to do this
917
918Coroutine_Err_NoStack
919: Not enough stack is available
920
921Coroutine_Err_CoroutineFromWrongThread
922: Trying to do something on one thread to a `Coroutine` from a different thread
923
924Coroutine_Err_ACoroutineIsAlreadyRunning
925: Trying `Coroutine_RunCoroutine` a `Coroutine`
926
927Coroutine_Err_ExitWithRunningCoroutines
928: All `Coroutine`s must be complete
929
930Coroutine_Err_StackOverrun
931: Stack overrun detected
932
933Coroutine_Err_InternalInsistency
934: Something didn't match inside the system
935
936Coroutine_Err_CouldNotInitialiseSystem
937: Something went wrong initialising (eg couldn't create a lock)
938
939Coroutine_Err_WrongState
940: It's in the wrong statem, eg trying to `Coroutine_Continue` a completed `Coroutine`
941
942Coroutine_Err_Canceled
943: It's canceled
944
945##### Coroutine_SetStackLimit(void *limit)
946
947limit
948: The location (low address) of the stack's end.
949
950Set the limit of the stack. This is used to determine more accurately whether `Coroutine_CanStartCoroutine()`
951
952##### Coroutine_Report Coroutine_GetReport()
953
954(returns)
955: A report from this run of the Coroutine system.
956
957 #!C
958 typedef struct Coroutine_Report {
959 unsigned coroutines_created;
960 unsigned coroutines_pool_size;
961 unsigned lowest_headroom;
962 } Coroutine_Report;
963
964coroutines_created
965: How many coroutines were created
966
967coroutines_pool_size
968: The size of the coroutine pool (count of available, free `Coroutine` objects) when the system stopped. This is also the peak number of active coroutines. This will give you an idea of how much stack was needed for your coroutines.
969
970lowest_headroom
971: The lowest headroom (unused
972
973largest_stack
974: The largest stack requested for any `Coroutine`.
975
976##### Coroutine_CheckIntegrity()
977
978(returns)
979: `Coroutine_Err` for any problem
980
981Check the integrity of the coroutine system, and `printf()` any problems.
982
983##### Coroutine_Start
984
985 #!C
986 void *(*)(void *param)
987
988The entry function for a coroutine. The `param` is the value passed to `Coroutine_Continue`, and the `void *` return value can be accessed through the `Coroutine` object using `Coroutine_GetValue()`.
989
990##### Coroutine_SystemStart
991
992 #!C
993 Coroutine_Err (*)(void *param, Coroutine *root_coroutine)
994
995The entry function for `Coroutine_RunSystem`.
996
997(returns)
998: An error if one occurs.
999
1000param
1001: The parameter passed in to `Coroutine_RunSystem`
1002
1003root_coroutine
1004: The coroutine that this callback is running in
1005
1006##### Coroutine_Err Coroutine_RunSystem(size_t min_size, size_t min_headroom, Coroutine_SystemStart start, void *value)
1007
1008(returns)
1009: `Coroutine_OK` or an error. If the system starts, this will be the value returned by `start`.
1010
1011min_size
1012: The minimum stack size to keep for the root coroutine.
1013
1014min_headroom
1015: The minimum headroom to keep for the root coroutine.
1016
1017start
1018: The function to call with the `Coroutine` system started. It is expected that this routine will
1019start a `Coroutine`.
1020
1021value
1022: The value to pass to `start`.
1023
1024##### Coroutine *Coroutine_New(size_t min_size, size_t min_headroom, Coroutine_Start start)
1025
1026(returns)
1027A new Coroutine, or `NULL` if there was a failure, such as insufficient stack for the new Coroutine.
1028
1029min_size
1030: The minimum stack size to keep for this Coroutine.
1031
1032min_headorom
1033: The minimum stack headroom to keep for this Coroutine.
1034
1035start
1036: The routine called to start the Coroutine.
1037
1038Create a new `Coroutine`. The `Coroutine` system must be started to create a `Coroutine`. The stack size available to the coroutine will be `COROUTINE_STACK_SIZE` defined in `coroutine.h`. When you have finished with your `Coroutine`, use `Coroutine_Delete()` to delete it. If there is not enough space for a new `Coroutine` on your stack, `NULL` will be returned.
1039
1040##### Coroutine_Err Coroutine_Run(size_t min_size, size_t min_headroom, Coroutine_Start start, void *value, void **result)
1041
1042(returns)
1043: `Coroutine_OK` or any problem
1044
1045min_size
1046: The minimum stack size to keep for this Coroutine.
1047
1048min_headorom
1049: The minimum stack headroom to keep for this Coroutine.
1050
1051start
1052: The routine to start the Coroutine.
1053
1054value
1055: The value to pass to `start()`.
1056
1057result
1058: Where to store the return value from `start(value)`. This may be `NULL`.
1059
1060`start(value)` is called from within a coroutine and its value returned in `*result`.
1061If this completes without any failure, `false` is returned, otherwise, typically
1062because `Coroutine_New()` returned `NULL`, `true` is returned. `result` may be `NULL` if you don't
1063need the resturn value from `start()`.
1064When the coroutine system is active - you are already running in a coroutine - `start(value)`
1065is simply called and its result returned in `*result`. When the Coroutine system is not running,
1066`Coroutine_Run()` starts it, creates a `Coroutine` and runs that Coroutine to call `start(calue)`
1067and return value is returned in `*result`, then stops the Coroutine system. If you need to force
1068a new Coroutine to be created, with a particular stack size to call `start(value)`, then use
1069`Coroutine_Chain()` instead.
1070
1071The total stack allowed for all coroutines running on any thread is the size of the call stack on that thread.
1072
1073##### void Coroutine_Delete(Coroutine *cor)
1074
1075cor
1076: The Coroutine to delete.
1077
1078Use `Coroutine_Delete()` to delete a coroutine when it is no longer needed. It is an error to attempt to delete a coroutine which is running.
1079
1080##### Coroutine_Err Coroutine_Continue(Coroutine *cor, void *value, bool early)
1081
1082(returns)
1083: `Coroutine_OK` or any error.
1084
1085cor
1086: The Coroutine to continue.
1087
1088value
1089: The value to return from `cor`'s yield function.
1090
1091early
1092: Whether to continue `cor` early (`true`), or late (`false`). Early means before other Coroutines which are waiting
1093to be called, whereas late means after them.
1094
1095Continue the given `Coroutine`. `value` is passed to the coroutine, as `param` to the `start` function, or as the return value from `Coroutine_Yield`. `early` determines whether the continued coroutine will be run next, or after all the other, currently runnable, coroutines. If the `Coroutine` is already runnable, nothing is done, and `false` is returned. If the `Coroutine` is free, or complete, nothing is done and `true` is returned to show there was a problem.
1096
1097##### void *Coroutine_Yield(void *value, Coroutine_YieldCallback on_yield, void *this)
1098
1099value
1100: The value to yield fropm the coroutine.
1101
1102on_yield
1103: A callback to be called once this Coroutine has yielded, but before another one has been continued.
1104
1105this
1106: The parameter to pass to `on_yield`.
1107
1108Yield `value` from the current coroutine; this coroutine is moved to the list of coroutines waiting to be continued.
1109
1110When the current coroutine had been paused, `on_yield(this)` is called, with the expectation it might adjust which coroutines are ready to be run.
1111
1112When `on_yield(this)` returns, the next runable coroutine is run - either by its start routine being called with `value` as its `param`, or by `value`being returned from its `Coroutine_Yield()`.
1113
1114##### void *Coroutine_GetValue(Coroutine *cor)
1115
1116(returns)
1117: The Coroutine's value - the last yielded or returned value.
1118
1119cor
1120: The Coroutine to query.
1121
1122Return the `Coroutine`'s value - the value last yielded, or returned by its `start` routine.
1123
1124##### Coroutine *Coroutine_GetActive()
1125
1126(returns)
1127: The currently active Coroutine.
1128
1129Return whihc coroutine is currently running, ie the caller's `Coroutine`.
1130
1131##### bool Coroutine_IsRunning(Coroutine *cor)
1132
1133(returns)
1134: Whether `cor` is running - it's the active coroutine or waiting to be continued.
1135
1136cor
1137: The Coroutine to query.
1138
1139Return whether the given coroutine is still running - it may be running, ready to run, or waiting to be continued, but won't have returned from its `start` function.
1140
1141##### bool Coroutine_IsComplete(Coroutine *cor)
1142
1143(returns)
1144: Whether `cor` is complete, ie has returned from `start()`./
1145
1146cor
1147: The Coroutine to query.
1148
1149Return whether the given coroutine is complete - is has returned from its `start` function.
1150
1151##### intptr_t Coroutine_GetStackHeadroom()
1152
1153(returns)
1154: The amount of stack headroom.
1155
1156Return the headroom available in the current coroutine's stack. This can be used to detect when your coroutine is nearing its stack limit, and then use `Coroutine_Chain()` to continue in a new chunk of coroutine stack.
1157
1158##### bool Coroutine_CanStartCoroutine(size_t size)
1159
1160(returns)
1161: Whether a Coroutine with the given amount of stack could be created.
1162
1163size
1164: The amount of stack in the Coroutine we might want to create.
1165
1166Return whether the coroutine system can start a new coroutine. This check can only be done with the coroutine system active (currently running
1167a coroutine). If there's a free coroutine, or enough space on the stack for a new one, then this will return `true`. To set the limit of the
1168stack use `Coroutine_SetStackLimit()`
1169
1170##### size_t Coroutine_GetUsefulFreeSpace(size_t overhead)
1171
1172(returns)
1173: The total amount of useful free space in the Coroutine system.
1174
1175min_size
1176: Ignore free blocks smaller than this.
1177
1178overhead
1179: The amount of overhead in each free block.
1180
1181Each Coroutine is assumed to have an amount of unusable space. In an application
1182where coroutines are chained, this might be minimum headroom before the the next
1183coroutine is chained to - whatever space is left unused is the overhead. Passing
1184this minimum headroom to `Coroutine_GetUsefulFreeSpace`, means it will return a
1185conservative estimate of the amount of actually usable stack space available to
1186chain to.
1187
1188##### void *Coroutine_GetStackHWM(void)
1189
1190(returns)
1191: The lowest address where the active Coroutine's stack has grown to ever.
1192
1193Find out where this coroutine's guard patterns end. This is intended as a part of the tools to measure how much stack something is using:
1194
1195 #!C
1196 Coroutine_ClearStackForHWM();
1197 char *before = (char *)Coroutine_GetStackHWM();
1198 // do the thing you want to measure here
1199 char *after = (char *)Coroutine_GetStackHWM();
1200 intptr_t amount_used = before - after;
1201
1202##### void Coroutine_ClearStackForHWM(void)
1203
1204Fill the unused stack in this coroutine with a guard pattern. This is intended as a part of the tools to measure how much stack something is using:
1205
1206 #!C
1207 Coroutine_ClearStackForHWM();
1208 char *before = (char *)Coroutine_GetStackHWM();
1209 // do the thing you want to measure here
1210 char *after = (char *)Coroutine_GetStackHWM();
1211 intptr_t amount_used = before - after;
1212
1213##### void *Coroutine_GetCStackTop()
1214
1215(returns)
1216: Where the Coroutine system has reached in the C stack.
1217
1218Return an address which is near to the top of used C stack.
1219
1220##### Coroutine_Err Coroutine_Chain(size_t min_size, size_t min_headroom, Coroutine_Start start, void *value, void **result)
1221
1222(returns)
1223: Whether there was a problem. `Coroutine_OK` - `start(value)` was run; an error - there was a problem.
1224
1225min_size
1226: The amount of stack to keep for the chained Coroutine.
1227
1228min_headroom
1229: The amount of stack headroom to keep for the chained Coroutine.
1230
1231start
1232: The entry point ot the chained Coroutine.
1233
1234value
1235: The value to pass to `start()`
1236
1237result
1238: Where to store the return value from `start(value)`. This may be `NULL`.
1239
1240Run `start` with `value` on a new coroutine, and return its return value in `*result` (`result`
1241may be NULL). It is expected that `Coroutine_Chain()` will be used when your coroutine is running short
1242of stack - it is not an alternative to `Coroutine_Run()`.
1243
1244The chain of coroutines is hidden - the 'active' coroutine is the outermost coroutine
1245in the chain, and that coroutine's value is whatever was yielded by the innermost coroutine. Continuing
1246the outermost coroutine will continue the tip coroutine in the chain, ie the one which yielded.
1247
1248##### Coroutine_Err Coroutine_CallWithMaxStack(Coroutine_Start start, void *value, void **result)
1249
1250(returns)
1251: Whether there was a problem. `Coroutine_OK` - `start(value)` was run; an error - there was a problem.
1252
1253start
1254: The entry point ot the chained Coroutine.
1255
1256value
1257: The value to pass to `start()`
1258
1259result
1260: Where to store the return value from `start(value)`. This may be `NULL`.
1261
1262Call `start(value)`, and ensure it has as much stack as possible. Sometimes you don't know
1263how much stack you will need to call a function. This would be normal for many OS functions
1264(eg loading a library), or 3rd party library functions. In those cases, use this function to
1265ensure as much stack as possible is available.
1266
1267Inside Coroutine: If a new coroutine would have more
1268stack than the calling one then `start(value)` will be chained, using the same `min_size` and `min_headroom`
1269settings as the calling coroutine. If the calling coroutine has the most stack possible then `start(value)` is just called.
1270
1271The chain of coroutines is hidden - the 'active' coroutine is the outermost coroutine
1272in the chain, and that coroutine's value is whatever was yielded by the innermost coroutine. Continuing
1273the outermost coroutine will continue the tip coroutine in the chain, ie the one which yielded.
1274
1275##### void Coroutine_Dump_()
1276
1277*Do not use this function in production code*
1278
1279This prints the current state of the Coroutine system. It is used for development, and is not part of the official interface.
1280