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