2 contributors
856 lines25.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## Prerequisites
11
12These 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, `pthread.h` has been used instead.
13
14You will need to build & link the code, `coroutine/*.c`, as part of your system, and ensure the headers, `include/*`, are available on your include path.
15
16## Quick Start
17
18### Tasks
19
20To run `Task`s:
21
22 #!C
23 #include "coroutine.h"
24 #include "task.h"
25 main(){
26 Coroutine_StartSystem();
27 void *res = NULL;
28 bool canceled = Task_Run(maintask, &param, &res);
29 Coroutine_StopSystem();
30 }
31
32`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:
33
34 #!C
35 bool mytask(void *param, void **res){
36
37 // do your thing here
38
39 return canceled;
40 }
41
42When `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.
43
44Within your main task, create `Task`s and `Task_Await()` them when you want to wait for their result:
45
46 #!C
47 Task task1;
48 Task_ctor(&task1, adifferenttask, &task1param);
49
50 void *result;
51 bool canceled = Task_Await(&task1, &result);
52
53 Task_dtor(&task1);
54
55 // use the result
56
57When a task needs to wait for something, and wants to allow other tasks to run, it should use a `Future`:
58
59 #!C
60 Future future;
61 Future_ctor(&future);
62
63 // pass the future to the background-thing-which-might-take-a-while
64
65 void *res;
66 bool canceled = Future_Await(&future, &res);
67
68 Future_dtor(&future);
69
70When the background-thing-which-might-take-a-while has a result:
71
72 #!C
73 Future_SetResult(future, false, result);
74
75### ASleep
76
77`ASleep()` needs its own system to be started to work:
78
79 #!C
80 ASleep_StartSystem()
81 Coroutine_StartSystem();
82 // Run tasks here which may now use ASLeep()
83 Coroutine_StopSystem();
84 ASleep_StopSystem();
85
86Note that `ASleep_StartSystem()` / `ASleep_StopSystem()` is only needed once per process, whereas `Coroutine_StartSystem()` / `Coroutine_StopSystem()` is needed on each thread where coroutines are used.
87
88Sleeping in a task:
89
90 #!C
91 bool mytask(void *param, void **result){
92 ..
93 ASleep(time_to_sleep);
94 ..
95 }
96
97### Generators
98
99The coroutine system needs to be started:
100
101 #!C
102 Coroutine_StartSYstem();
103 // you can use generators now
104 Coroutine_StopSystem();
105
106Note that you need to start the coroutine system on each thread you want to use them.
107
108You will need a generator function:
109
110 #!C
111 void *yield_my_things(void *param){
112 bool domore = true;
113
114 // loop/call functions to find more values to yield, and when you have one:
115 domore = Generator_Yield(thing);
116 // .. if domore is false, exit your generator - it is being destructed
117
118 // not actually used by generators, but this is a useful convention for bubbling
119 // the flag out to calling functions.
120 return (void *)domore;
121 }
122
123And to use it:
124
125 #!C
126 Generator gen;
127 Generator_ctor(&gen, yield_my_things, "..");
128 void *thing;
129 while(Generator_Next(&gen, &thing)){
130 // use thing - a value yielded by your generator
131 }
132 Generator_dtor(&gen);
133
134### Coroutines
135
136While you can use coroutines directly, it's designed as a system to support more useful patterns, like `Async` and `Generators`.
137
138The Coroutines system must be started:
139
140 #!C
141 Coroutine_StartSystem();
142 // use coroutines here
143 Coroutine_StopSystem();
144
145Your coroutine will need to have a start function:
146
147 #!C
148 void *start(void *param){
149 ...
150 }
151
152When there is no coroutine running, start your 'main' coroutine:
153
154 #!C
155 void *result = Coroutine_Run(comain, param);
156
157Create other coroutines like this:
158
159 #!C
160 Coroutine *cor = Coroutine_New(start);
161
162When you want a Coroutine to run, or to return from a yield:
163
164 #!C
165 Coroutine_Continue(cor, value, run_early);
166
167`value` will be start function's parameter, or the value returned from the yield.
168
169Within the Coroutine, to yield a value:
170
171 #!C
172 void *Coroutine_Yield(value, on_yield, void *me);
173
174The on_yield function is called after the coroutine has been 'wait'ed, but before the next coroutine is resumed.
175
176## How it Works
177
178The coroutine system uses the stack divided into smaller stacks for the coroutines. This means you may need to consider whether the coroutine stack size, set by `COROUTINE_STARTUP_STACK_SIZE`, is right for your application, and whether your stack size is enough for the number of coroutines you might run.
179
180Each 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.
181
182## Style
183
184The 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()`.
185
186 #!C
187 Something *oneofthem = Something_New();
188 // use oneofthem
189 Something_Delete(oneofthem);
190
191Can be also be done like this, and this will run faster:
192
193 #!C
194 Something oneofthem;
195 Something_ctor(&oneofthem);
196 // use oneofthem
197 Something_dtor(&oneofthem);
198
199The 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.
200
201## Usage
202
203When you are using coroutines or generators:
204
205 #!C
206 void *myfunc(void *){
207 // your function here
208 }
209
210 Coroutine_StartSystem();
211 Coroutine_Run(myfunc, (void *)myparam);
212 Coroutine_StopSystem();
213
214While the system is started, you can make many calls to `Coroutine_Run()` or `Task_Run()`, but only one of them can be running at once. A running system is thread local - each thread you want to use coroutines on will need to be `Coroutine_StartSystem()`ed.
215
216## Stack Overruns
217
218The C stack is divided down into smaller stacks. There's one to give some work room between `..StartSystem()` and `..Run()`, and one for each coroutine. 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:
219
220* Use less stack. This is, sometimes, the right advice, especially if the startup stack overrins. The expectation is that very little is done between `.._StartSystem()` and `..Run()`. If your situation needs more doing, you can...
221
222* increase the stack size. Adjust `COROUTINE_STACK_SIZE` (for startup) or `COROUTINE_STARTUP_STACK_SIZE` (for coroutines) as appropriate. 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...
223
224* monitor stack headroom, and add another stack chunk if you need to:
225
226In this last case you'll need to add some code at key points:
227
228 #!C
229 void *myfunction(void *param){
230 if (Coroutine_GetStackHeadroom() < MIN_ALLOWED_STACK){
231 return Coroutine_Chain(myfunction, param);
232 }
233 // do everything normally
234 }
235
236More realistically:
237
238 #!C
239 struct myfunctionparams {
240 int a;
241 char *b;
242 struct dog *d;
243 }
244
245 void *mychain(void *param){
246 struct myfunctionparams *myparams = (struct myfunctionparams *)params;
247 return (void *)myfunction(myparams->a, myparams->b, *myparams->d);
248 }
249
250 int myfunction(int a, char *b, struct dog d){
251 if (Coroutine_GetStackHeadroom() < MIN_ALLOWED_STACK){
252 struct myfunctionparams params = {
253 a,
254 b,
255 &d
256 };
257 return (int)Coroutine_Chain(mychain, &params);
258 }
259 }
260
261And if you want to panic if the C stack overruns:
262
263 #!C
264 if (Coroutine_GetStackHeadroom() < MIN_ALLOWED_COROUTINE_STACK){
265 if (Coroutine_HasCoroutinesInFreePool() ||
266 (char *)Coroutine_GetCStackTop() - c_stack_end >= MIN_ALLOWED_C_STACK) {
267 struct myfunctionparams params = {
268 a,
269 b,
270 &d
271 };
272 return (int)Coroutine_Chain(mychain, &params);
273 }
274 // panic now
275 }
276
277# API
278
279## Task & Future
280
281The pattern for using async is:
282
283 #!C
284 bool mymaintask(void *param, void **result){
285 // do your main task things here, like starting more tasks
286 }
287
288 Coroutine_StartSystem();
289 void *res = NULL;
290 bool canceled = Task_Run(mymaintask, NULL, &res);
291 Coroutine_StopSystem();
292
293To create and wait for a task:
294
295 #!C
296 Task task1;
297 Task_ctor(&task1, asynctask1, &task1param);
298 void *res = NULL;
299 bool canceled = Task_Await(&task1, void **res)
300 Task_dtor(&task1);
301
302or, if you prefer new & delete:
303
304 #!C
305 Task *task1 = Task_New(asynctask1, &task1param);
306 void *res = NULL;
307 bool canceled = Task_Await(task1, void **res)
308 Task_Delete(task1);
309
310Inside 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:
311
312 #!C
313 Future future;
314 Future_ctor(&future);
315
316 // keep &future to hand for when the background thing completes
317 bool canceled = Future_Await(&future, NULL);
318
319 Future_dtor(&future);
320
321`Future_New()` and `Future_Delete()` are also available if you prefer that style.
322
323Inside the callback when the background thing is complete:
324
325 #!C
326 // result is a void *
327 Future_SetResult(future, result, false);
328
329or, if something went wrong:
330
331 #!C
332 // exception is a void *
333 Future_SetResult(future, exception, true);
334
335Back in the task, you can respond to the future:
336
337 #!C
338 ... Future_Await has returned
339 if (canceled){
340 // exit quickly - you've been canceled
341 // you could, for example, use the future's result as an exception, or error code here
342 }
343 // carry on - the future's result may be an actual result, that's up to you
344
345
346##### void Future_ctor(Future *fut)
347
348fut
349: The `Future` being constructed
350
351Initialise a future. When you no longer need it, use `Future_dtor()`.
352
353##### Future *Future_New()
354
355(returns)
356: The new future
357
358Allocates and initialises a future, When you no longer need it, use `Future_Delete()`.
359
360##### void Future_dtor(Future *fut)
361
362fut
363: The `Future` being destructed
364
365Destruct a future previously constructed with `Future_ctor()`.
366
367##### void Future_Delete(Future *fut)
368
369fut
370: The `Future` to be destructed and freed
371
372Delete (finalise and free) a future previously new'ed with `Future_New()`
373
374##### void Future_SetResult(Future *fut, bool canceled, void *value)
375
376fut
377: The `Future` whose result is being set
378
379canceled
380: The future's `canceled` setting
381
382value
383: The future's result `value`
384
385Set 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.
386
387The `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 *`.
388
389##### bool Future_GetResult(Future *fut, void **res)
390
391(returns)
392: The `canceled` value of the `Future`.
393
394res
395: Where to store the value of the `Future`. This may be `NULL`.
396
397Get the result of a future.
398
399##### typedef void (*Future_Watcher)(void *me, Future *fut)
400
401A `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.
402
403##### void Future_AddWatcher(Future *fut, Future_Watcher watcher, void *me)
404
405fut
406: the `Future` to add a watcher to
407
408watcher
409: the callback to call when the `Future` has a result.
410
411me
412: the `me` value to pass to `watcher` when it is called back.
413
414Add 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.
415
416##### void Future_RemoveWatcher(Future *fut, Future_Watcher watcher, void *me)
417
418fut
419: the `Future` to remove a watcher from
420
421watcher
422: the callback of the watcher to remove.
423
424me
425: the `me` value of the watcher to remove.
426
427Remove 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.
428
429##### bool Future_Await(Future *fut, void **res)
430
431(returns)
432: whether the `Future` was canceled.
433
434fut
435: The `Future` to wait for.
436
437res
438: Where to store the `value` of the future when it is has a result. May be `NULL`.
439
440The current `Task` is paused until the `Future` has a result. Other `Task`s are run while this one is waiting.
441
442##### typedef bool (*Task_Entry)(void *param, void **res)
443
444The entry function to an `Task`.
445
446##### void Task_ctor(Task *tsk, Task_Entry entry, void *param)
447
448tsk
449: The task to construct.
450
451entry
452: The entry function for the task.
453
454param
455: The value for `param` to pass to `entry`.
456
457Initialises an `Task`. When you have finished with an `Task` you must finalise it using `Task_dtor()`
458
459 #!C
460 Task tsk;
461 Task_ctor(&tsk, mytask, myparam);
462 // tsk will run if you wait for a task or future
463 Task_Await(&tsk, NULL);
464 Task_dtor(&tsk);
465
466##### Task *Task_New(Task_Entry entry, void *param)
467
468(returns)
469: The new `Task`.
470
471entry
472: The entry function for the task.
473
474param
475: The value for `param` to pass to `entry`.
476
477This allocates and initialises a new `Task`. When you have finished with your task, you must `Task_Delete()` it.
478
479 #!C
480 Task *tsk = Task_New(mytask, myparam);
481 // tsk will run if you wait for a task or future
482 Task_Await(tsk, NULL);
483 Task_Delete(tsk);
484
485##### void Task_dtor(Task *tsk)
486
487tsk
488: The `Task` to destruct.
489
490This finalises an `Task` you ealier initalised with `Task_ctor()`. It is an error to attempt to destruct a task which is running.
491
492 #!C
493 Task tsk;
494 Task_ctor(&tsk, mytask, myparam);
495 // use tsk
496 Task_dtor(&tsk);
497
498##### void Task_Delete(Task *tsk)
499
500tsk
501: The `Task` to delete.
502
503This 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.
504
505 #!C
506 Task *tsk = Task_New(mytask, myparam);
507 // use tsk
508 Task_Delete(tsk);
509
510##### static inline bool Task_Await(Task *tsk, void **res)
511
512(returns)
513: Whether the task was canceled.
514
515tsk
516: The `Task` to wait for.
517
518res
519: Where to store the `Task`'s value when it finishes. This may be NULL.
520
521The current `Task` waits for `tsk` to finish, and returns the result.
522
523##### void Task_Cancel(Task *tsk, void *cancel_value)
524
525tsk
526: The task to cancel.
527
528cancel_value
529: The value to set on any future this task waits on.
530
531This marks a task as canceled. When that task waits on a future that future will be canceled too, using `cancel_value`.
532
533##### static inline bool Task_IsCanceled(Task *tsk)
534
535(returns)
536: Whether the task is canceled.
537
538tsk
539: The task to get its canceled setting from.
540
541##### static inline Future *Task_GetAwaitedFuture(Task *tsk)
542
543(returns)
544: The future the task is waiting on. May be NULL.
545
546tsk
547: Teh task to read the future it is waiting on.
548
549Return the future a task is waiting on.
550
551##### bool Task_Run(Task_Entry start, void *value, void **res)
552
553(returns)
554: Whether `start` was canceled.
555
556start
557: The function to use as the main task.
558
559value
560: The value to pass to `start`.
561
562res
563: Where to store the result of `start`.
564
565Runs `start` as an `Task`. When `start` returns all other tasks must have been destructed, using `Task_dtor()` or `Task_Delete()`.
566
567## ASleep
568
569##### void ASleep_StartSystem()
570
571You must start the `ASleep` system to use it. This needs to happen per process (whereas `Coroutine_StartSystem()` needs to happen per-thread). Once you've finished with `ASleep` you must `ASleep_StopSystem()`.
572
573 #!C
574 ASleep_StartSystem();
575 // Now you can use ASleep() on any thread
576 ASleep_StopSystem();
577
578##### void ASleep_StopSystem()
579
580Call this to stop the `ASleep` system.
581
582##### bool ASleep(float delay, void **value)
583
584(returns)
585: Whether the task was canceled.
586
587delay
588: How many seconds to delay for.
589
590value
591: Where to store the cancellation value. This may be NULL.
592
593Sleep for `delay` seconds. `*value` will be set to `NULL` if the sleep is successful, and the `cancel_value` if the task is canceled.
594
595## Generator
596
597The pattern for a `Generator` is:
598
599#### A loop which uses the `Generator
600
601 #!C
602 Generator gen;
603 Generator_ctor(&gen, mygen, &param);
604
605 void *value;
606 while(Generator_Next(&gen, &value)){
607 // use value here
608 }
609 // value is now the return value from the Generator
610
611 Generator_dtor(&gen);
612
613Or:
614
615 #!C
616 Generator *gen = Generator_New(mygen, &param);
617
618 void *value;
619 while(Generator_Next(gen, &value)){
620 // use value here
621 }
622
623 Generator_Delete(gen);
624
625`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.
626
627#### A generator function
628
629 #!C
630 void *mygen(void *param){
631 bool domore = true;
632 // The parameter is a pointer to a string of chars
633 for (char *str = param; *str; ++str) {
634 // The value yielded is a pointer to a character in the string
635 domore = Generator_Yield(str);
636 if (!domore){
637 break;
638 }
639 }
640
641 return (void *)domore;
642 }
643
644The `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.
645
646##### void Generator_ctor(Generator *gen, void *(*start)(void *), void *param)
647
648gen
649: The `Generator` to construct.
650
651start
652: The function which is the start/entry-point of the `Generator`.
653
654param
655: The value to pass to `start`.
656
657Initialise a `Generator`. When you no longer need the `Generator`, use `Generator_dtor()` to destruct it.
658
659 #!C
660 Generator gen;
661 Generator_ctor(&gen, mystart, &params);
662
663 // Generator is used
664
665 // ... later:
666 Generator_dtor(&gen);
667
668##### Generator *Generator_New(void *(*start)(void *), void *param)
669
670start
671: The function which is the start/entry-point of the `Generator`.
672
673param
674: The value to pass to `start`.
675
676`new` a `Generator` - malloc, and initialise it. When you no longer need the `Generator` use `Generator_dtor` to finalise it.
677
678 #!C
679 Generator *gen = Generator_New(mystart, &params);
680
681 // Generator is used
682
683 // ... later:
684 Generator_Delete(gen);
685
686##### void Generator_dtor(Generator *gen)
687
688gen
689: The `Generator` to destruct.
690
691Finalise a `Generator`. Once a `Generator` is no longer needed, it must be finalised:
692
693 #!C
694 // earlier...
695 Generator gen;
696 Generator_ctor(&gen, mystart, &params);
697
698 // Generator is used
699
700 // the Generator is no longer needed
701 Generator_dtor(&gen);
702
703
704##### void Generator_Delete(Generator *gen)
705
706gen
707: The `Generator` to delete.
708
709Finalise then `free()` a `Generator`. Once a `new`ed `Generator` is no longer needed, it must be deleted:
710
711 #!C
712 // earlier...
713 Generator *gen = Generator_New(mystart, &params);
714
715 // Generator is used
716
717 // the Generator is no longer needed
718 Generator_Delete(gen);
719
720
721##### bool Generator_Next(Generator *gen, void **value)
722
723(returns)
724: Whether there is a next value. `true` - there is a next value; `false` - the `Generator` has finished
725
726gen
727: The `Generator` to get the next value from.
728
729value
730: Where to store the next value.
731
732Get the next value yielded by the `Generator`.
733
734 #!C
735 void *value;
736 while(Generator_Next(gen, &value)){
737 // use value here
738 }
739
740The `Generator` feeds values to its client using `Generator_Yield()` - it is these values which `Generator_Next()` sets, in the example, `value` to.
741
742 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`.
743
744##### bool Generator_Yield(void *value)
745
746(returns)
747: Whether the `Generator` should do more.
748
749value
750: The `Generator`'s next value.
751
752Yield a value from a `Generator`.
753
754 #!C
755 bool domore = Generator_Yield(value);
756
757`value` is then provided by `Generator_Next()` as the next value from the generator.
758
759The `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.
760
761## Coroutine
762
763##### void Coroutine_StartSystem()
764
765Start the coroutine system on this thread. When you've finished with `Coroutine` must call `Coroutine_Stop()`.
766
767 #!C
768 Coroutine_Start();
769 // prepare
770 void *result = Coroutine_Run(...);
771 // use result
772 Coroutine_Stop();
773
774`Coroutine` can be started & stopped many times. While `Coroutine` is started, `Coroutine_Run()` can be called any number of times.
775
776The total stack allowed for all coroutines running on any thread is the size of the call stack on that thread.
777
778##### Coroutine_Report Coroutine_StopSystem()
779
780Stop the coroutine system on this thread. A `Coroutine_Report` is returned, which summarises the coroutine activity on this thread:
781
782 #!C
783 typedef struct Coroutine_Report {
784 unsigned coroutines_created;
785 unsigned coroutines_pool_size;
786 unsigned lowest_headroom;
787 } Coroutine_Report;
788
789coroutines_created
790: How many coroutines were created
791
792coroutines_pool_size
793: 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.
794
795lowest_headroom
796: The lowest headroom (unused bytes before the guard word) any of the coroutine had.
797
798##### Coroutine_Start
799
800 #!C
801 void *(*)(void *param)
802
803The 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()`.
804
805##### Coroutine *Coroutine_New(Coroutine_Start start)
806
807Create 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.
808
809##### void Coroutine_Run_Coroutine(Coroutine *cor, void *value)
810
811Run the `Coroutine` and return when it returns. This is how to start coroutines running in the coroutine system. It is an error for the run coroutine to return before all other coroutines have completed.
812
813##### void *Coroutine_Run(Coroutine_Start start, void *value)
814
815Convenience wrapper for `Coroutine_Run_Coroutine` which creates the `Coroutine` and retrieves its result.
816
817##### void Coroutine_Delete(Coroutine *cor)
818
819Use `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.
820
821##### void Coroutine_Continue(Coroutine *cor, void *value, bool early)
822
823Continue 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 is added to the head of tail of the list of runable coroutines.
824
825##### void *Coroutine_Yield(void *value, Coroutine_YieldCallback on_yield, void *this)
826
827Yield `value` from the current coroutine; this coroutine is moved to the list of coroutines waiting to be continued. 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()`.
828
829##### void *Coroutine_GetValue(Coroutine *cor)
830
831Return the `Coroutine`'s value - the value last yielded, or returned by its `start` routine.
832
833##### Coroutine *Coroutine_GetActive()
834
835Return whihc coroutine is currently running, ie the caller's `Coroutine`.
836
837##### bool Coroutine_IsRunning(Coroutine *cor)
838
839Return 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.
840
841##### int Coroutine_GetStackHeadroom()
842
843Return 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.
844
845##### bool Coroutine_HasCoroutinesInFreePool()
846
847Return whether the coroutine system has any coroutine stacks available in its coroutine stack free pool.
848
849##### void *Coroutine_GetCStackTop()
850
851Return an address which is near to the top of used C stack.
852
853##### void *Coroutine_Chain(Coroutine_Start start, void *value)
854
855Run `start` with `value` on a new coroutine, and return its return value. It is expected that `Coroutine_Chain()` will be used when your coroutine is running short of stack - it is not an alternative to `Coroutine_Run()`.
856