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