2 contributors
1190 lines36.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## 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
357`cor_platform.h` has customisations for your particular use case.
358
359_Cor_thread_local
360: How to declare a variable to be thread local
361
362COROUTINE_HAVE_ALLOCA_H
363: Whether your system can `#incude <alloca.h>`.
364
365_Cor_Mutex and related routines
366: Your system's mutex.
367
368_Cor_Realtime_Now
369: Return a realtime clock value compatible with _Cor_Semaphore_Wait.
370
371_Cor_Semaphore and related routines
372: Semaphores on your system.
373
374_Cor_Thread and related routines
375: Threads on your system.
376
377`cor_platform_inc.h` has more customisation for your particular use case, for coroutine.h to use.
378
379Coroutine_NS(name)
380: This allows the `Coroutine_???()` functions to be given a different naming convention.
381
382Coroutine_API_FUNC(TYPE)
383: This allows tagging of functions to be accessible to loaded dlls.
384
385# API
386
387## Task & Future
388
389The pattern for using async is:
390
391 #!C
392 bool mymaintask(void *param, void **result){
393 // do your main task things here, like starting more tasks
394 }
395
396 void *res = NULL;
397 bool canceled = Task_Run(mymaintask, NULL, &res);
398
399To create and wait for a task:
400
401 #!C
402 Task task1;
403 Task_ctor(&task1, asynctask1, &task1param);
404 void *res = NULL;
405 bool canceled = Task_Await(&task1, void **res)
406 Task_dtor(&task1);
407
408or, if you prefer new & delete:
409
410 #!C
411 Task *task1 = Task_New(asynctask1, &task1param);
412 void *res = NULL;
413 bool canceled = Task_Await(task1, void **res)
414 Task_Delete(task1);
415
416Inside 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:
417
418 #!C
419 Future future;
420 Future_ctor(&future);
421
422 // keep &future to hand for when the background thing completes
423 bool canceled = Future_Await(&future, NULL);
424
425 Future_dtor(&future);
426
427`Future_New()` and `Future_Delete()` are also available if you prefer that style.
428
429Inside the callback when the background thing is complete:
430
431 #!C
432 // result is a void *
433 Future_SetResult(future, result, false);
434
435or, if something went wrong:
436
437 #!C
438 // exception is a void *
439 Future_SetResult(future, exception, true);
440
441Back in the task, you can respond to the future:
442
443 #!C
444 ... Future_Await has returned
445 if (canceled){
446 // exit quickly - you've been canceled
447 // you could, for example, use the future's result as an exception, or error code here
448 }
449 // carry on - the future's result may be an actual result, that's up to you
450
451
452##### void Future_ctor(Future *fut)
453
454fut
455: The `Future` being constructed
456
457Initialise a future. When you no longer need it, use `Future_dtor()`.
458
459##### Future *Future_New()
460
461(returns)
462: The new future
463
464Allocates and initialises a future, When you no longer need it, use `Future_Delete()`.
465
466##### void Future_dtor(Future *fut)
467
468fut
469: The `Future` being destructed
470
471Destruct a future previously constructed with `Future_ctor()`.
472
473##### void Future_Delete(Future *fut)
474
475fut
476: The `Future` to be destructed and freed
477
478Delete (finalise and free) a future previously new'ed with `Future_New()`
479
480##### void Future_SetResult(Future *fut, bool canceled, void *value)
481
482fut
483: The `Future` whose result is being set
484
485canceled
486: The future's `canceled` setting
487
488value
489: The future's result `value`
490
491Set 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.
492
493The `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 *`.
494
495##### bool Future_GetResult(Future *fut, void **res)
496
497(returns)
498: The `canceled` value of the `Future`.
499
500res
501: Where to store the value of the `Future`. This may be `NULL`.
502
503Get the result of a future.
504
505##### typedef void (*Future_Watcher)(void *me, Future *fut)
506
507A `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.
508
509##### void Future_AddWatcher(Future *fut, Future_Watcher watcher, void *me)
510
511fut
512: the `Future` to add a watcher to
513
514watcher
515: the callback to call when the `Future` has a result.
516
517me
518: the `me` value to pass to `watcher` when it is called back.
519
520Add 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.
521
522##### void Future_RemoveWatcher(Future *fut, Future_Watcher watcher, void *me)
523
524fut
525: the `Future` to remove a watcher from
526
527watcher
528: the callback of the watcher to remove.
529
530me
531: the `me` value of the watcher to remove.
532
533Remove 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.
534
535##### bool Future_Await(Future *fut, void **res)
536
537(returns)
538: whether the `Future` was canceled.
539
540fut
541: The `Future` to wait for.
542
543res
544: Where to store the `value` of the future when it is has a result. May be `NULL`.
545
546The current `Task` is paused until the `Future` has a result. Other `Task`s are run while this one is waiting.
547
548##### typedef bool (*Task_Entry)(void *param, void **res)
549
550The entry function to an `Task`.
551
552##### void Task_ctor(Task *tsk, Task_Entry entry, void *param)
553
554tsk
555: The task to construct.
556
557entry
558: The entry function for the task.
559
560param
561: The value for `param` to pass to `entry`.
562
563Initialises an `Task`. When you have finished with an `Task` you must finalise it using `Task_dtor()`
564
565 #!C
566 Task tsk;
567 Task_ctor(&tsk, mytask, myparam);
568 // tsk will run if you wait for a task or future
569 Task_Await(&tsk, NULL);
570 Task_dtor(&tsk);
571
572##### Task *Task_New(Task_Entry entry, void *param)
573
574(returns)
575: The new `Task`.
576
577entry
578: The entry function for the task.
579
580param
581: The value for `param` to pass to `entry`.
582
583This allocates and initialises a new `Task`. When you have finished with your task, you must `Task_Delete()` it.
584
585 #!C
586 Task *tsk = Task_New(mytask, myparam);
587 // tsk will run if you wait for a task or future
588 Task_Await(tsk, NULL);
589 Task_Delete(tsk);
590
591##### void Task_dtor(Task *tsk)
592
593tsk
594: The `Task` to destruct.
595
596This finalises an `Task` you ealier initalised with `Task_ctor()`. It is an error to attempt to destruct a task which is running.
597
598 #!C
599 Task tsk;
600 Task_ctor(&tsk, mytask, myparam);
601 // use tsk
602 Task_dtor(&tsk);
603
604##### void Task_Delete(Task *tsk)
605
606tsk
607: The `Task` to delete.
608
609This 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.
610
611 #!C
612 Task *tsk = Task_New(mytask, myparam);
613 // use tsk
614 Task_Delete(tsk);
615
616##### static inline bool Task_Await(Task *tsk, void **res)
617
618(returns)
619: Whether the task was canceled.
620
621tsk
622: The `Task` to wait for.
623
624res
625: Where to store the `Task`'s value when it finishes. This may be NULL.
626
627The current `Task` waits for `tsk` to finish, and returns the result.
628
629##### void Task_Cancel(Task *tsk, void *cancel_value)
630
631tsk
632: The task to cancel.
633
634cancel_value
635: The value to set on any future this task waits on.
636
637This marks a task as canceled. When that task waits on a future that future will be canceled too, using `cancel_value`.
638
639##### static inline bool Task_IsCanceled(Task *tsk)
640
641(returns)
642: Whether the task is canceled.
643
644tsk
645: The task to get its canceled setting from.
646
647##### static inline Future *Task_GetAwaitedFuture(Task *tsk)
648
649(returns)
650: The future the task is waiting on. May be NULL.
651
652tsk
653: Teh task to read the future it is waiting on.
654
655Return the future a task is waiting on.
656
657##### bool Task_Run(Task_Entry start, void *value, void **res)
658
659(returns)
660: Whether `start` was canceled.
661
662start
663: The function to use as the main task.
664
665value
666: The value to pass to `start`.
667
668res
669: Where to store the result of `start`.
670
671Runs `start` as an `Task`. When `start` returns all other tasks must have been destructed, using `Task_dtor()` or `Task_Delete()`.
672
673## ASleep
674
675##### void ASleep_StartSystem()
676
677You must start the `ASleep` system to use it. This needs to happen per process. Once you've finished with `ASleep` you must `ASleep_StopSystem()`.
678
679 #!C
680 ASleep_StartSystem();
681 // Now you can use ASleep() on any thread
682 ASleep_StopSystem();
683
684##### void ASleep_StopSystem()
685
686Call this to stop the `ASleep` system.
687
688##### bool ASleep(float delay, void **value)
689
690(returns)
691: Whether the task was canceled.
692
693delay
694: How many seconds to delay for.
695
696value
697: Where to store the cancellation value. This may be NULL.
698
699Sleep for `delay` seconds. `*value` will be set to `NULL` if the sleep is successful, and the `cancel_value` if the task is canceled.
700
701## Generator
702
703The pattern for a `Generator` is:
704
705#### A loop which uses the `Generator
706
707 #!C
708 Generator gen;
709 Generator_ctor(&gen, generator_stack_size, mygen, &param);
710
711 void *value;
712 while(Generator_Next(&gen, &value)){
713 // use value here
714 }
715 // value is now the return value from the Generator
716
717 Generator_dtor(&gen);
718
719Or:
720
721 #!C
722 Generator *gen = Generator_New(generator_stack_size, mygen, &param);
723
724 void *value;
725 while(Generator_Next(gen, &value)){
726 // use value here
727 }
728
729 Generator_Delete(gen);
730
731`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.
732The `generator_stack_size` is the stack amount made available to your generator.
733
734#### A generator function
735
736 #!C
737 void *mygen(void *param){
738 bool domore = true;
739 // The parameter is a pointer to a string of chars
740 for (char *str = param; *str; ++str) {
741 // The value yielded is a pointer to a character in the string
742 domore = Generator_Yield(str);
743 if (!domore){
744 break;
745 }
746 }
747
748 return (void *)domore;
749 }
750
751The `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.
752
753##### void Generator_ctor(Generator *gen, size_t generator_stack_size, void *(*start)(void *), void *param)
754
755gen
756: The `Generator` to construct.
757
758generator_stack_size
759: The amount of stack given to the generator.
760
761start
762: The function which is the start/entry-point of the `Generator`.
763
764param
765: The value to pass to `start`.
766
767Initialise a `Generator`. When you no longer need the `Generator`, use `Generator_dtor()` to destruct it.
768
769 #!C
770 Generator gen;
771 Generator_ctor(&gen, generator_stack_size, mystart, &params);
772
773 // Generator is used
774
775 // ... later:
776 Generator_dtor(&gen);
777
778##### Generator *Generator_New(size_t generator_stack_size, void *(*start)(void *), void *param)
779
780generator_stack_size
781: The amount of stack to give to the generator.
782
783start
784: The function which is the start/entry-point of the `Generator`.
785
786param
787: The value to pass to `start`.
788
789`new` a `Generator` - malloc, and initialise it. When you no longer need the `Generator` use `Generator_dtor` to finalise it.
790
791 #!C
792 Generator *gen = Generator_New(mystart, &params);
793
794 // Generator is used
795
796 // ... later:
797 Generator_Delete(gen);
798
799##### void Generator_dtor(Generator *gen)
800
801gen
802: The `Generator` to destruct.
803
804Finalise a `Generator`. Once a `Generator` is no longer needed, it must be finalised:
805
806 #!C
807 // earlier...
808 Generator gen;
809 Generator_ctor(&gen, generator_stack_size, mystart, &params);
810
811 // Generator is used
812
813 // the Generator is no longer needed
814 Generator_dtor(&gen);
815
816
817##### void Generator_Delete(Generator *gen)
818
819gen
820: The `Generator` to delete.
821
822Finalise then `free()` a `Generator`. Once a `new`ed `Generator` is no longer needed, it must be deleted:
823
824 #!C
825 // earlier...
826 Generator *gen = Generator_New(mystart, &params);
827
828 // Generator is used
829
830 // the Generator is no longer needed
831 Generator_Delete(gen);
832
833
834##### bool Generator_Next(Generator *gen, void **value)
835
836(returns)
837: Whether there is a next value. `true` - there is a next value; `false` - the `Generator` has finished
838
839gen
840: The `Generator` to get the next value from.
841
842value
843: Where to store the next value.
844
845Get the next value yielded by the `Generator`.
846
847 #!C
848 void *value;
849 while(Generator_Next(gen, &value)){
850 // use value here
851 }
852
853The `Generator` feeds values to its client using `Generator_Yield()` - it is these values which `Generator_Next()` sets, in the example, `value` to.
854
855 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`.
856
857##### bool Generator_Yield(void *value)
858
859(returns)
860: Whether the `Generator` should do more.
861
862value
863: The `Generator`'s next value.
864
865Yield a value from a `Generator`.
866
867 #!C
868 bool domore = Generator_Yield(value);
869
870`value` is then provided by `Generator_Next()` as the next value from the generator.
871
872The `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.
873
874## Coroutine
875
876##### Coroutine_Err
877
878The enum of errors:
879
880Coroutine_OK
881: Everything is OK. This is 0
882
883Coroutine_Err_SystemNotRunning
884: A `Coroutine` must be running to do this
885
886Coroutine_Err_SystemRunning
887: The `Coroutine` system must not be running to do this
888
889Coroutine_Err_NoStack
890: Not enough stack is available
891
892Coroutine_Err_CoroutineFromWrongThread
893: Trying to do something on one thread to a `Coroutine` from a different thread
894
895Coroutine_Err_ACoroutineIsAlreadyRunning
896: Trying `Coroutine_RunCoroutine` a `Coroutine`
897
898Coroutine_Err_ExitWithRunningCoroutines
899: All `Coroutine`s must be complete
900
901Coroutine_Err_StackOverrun
902: Stack overrun detected
903
904Coroutine_Err_InternalInsistency
905: Something didn't match inside the system
906
907Coroutine_Err_CouldNotInitialiseSystem
908: Something went wrong initialising (eg couldn't create a lock)
909
910Coroutine_Err_WrongState
911: It's in the wrong statem, eg trying to `Coroutine_Continue` a completed `Coroutine`
912
913Coroutine_Err_Canceled
914: It's canceled
915
916##### Coroutine_SetStackLimit(void *limit)
917
918limit
919: The location (low address) of the stack's end.
920
921Set the limit of the stack. This is used to determine more accurately whether `Coroutine_CanStartCoroutine()`
922
923##### Coroutine_Report Coroutine_GetReport()
924
925(returns)
926: A report from this run of the Coroutine system.
927
928 #!C
929 typedef struct Coroutine_Report {
930 unsigned coroutines_created;
931 unsigned coroutines_pool_size;
932 unsigned lowest_headroom;
933 } Coroutine_Report;
934
935coroutines_created
936: How many coroutines were created
937
938coroutines_pool_size
939: 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.
940
941lowest_headroom
942: The lowest headroom (unused
943
944largest_stack
945: The largest stack requested for any `Coroutine`.
946
947##### Coroutine_CheckIntegrity()
948
949(returns)
950: `Coroutine_Err` for any problem
951
952Check the integrity of the coroutine system, and `printf()` any problems.
953
954##### Coroutine_Start
955
956 #!C
957 void *(*)(void *param)
958
959The 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()`.
960
961##### Coroutine_SystemStart
962
963 #!C
964 Coroutine_Err (*)(void *)
965
966The entry function for `Coroutine_RunSystem`.
967
968##### Coroutine_Err Coroutine_RunSystem(Coroutine_SystemStart start, void *value)
969
970(returns)
971: `Coroutine_OK` or an error. If the system starts, this will be the value returned by `start`.
972
973start
974: The function to call with the `Coroutine` system started. It is expected that this routine will
975start a `Coroutine`.
976
977value
978: The value to pass to `start`.
979
980##### Coroutine *Coroutine_New(size_t size, Coroutine_Start start)
981
982(returns)
983A new Coroutine, or `NULL` if there was a failure, such as insufficient stack for the new Coroutine.
984
985size
986: The stack size given to this Coroutine.
987
988start
989: The routine called to start the Coroutine.
990
991Create 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.
992
993##### Coroutine_Err Coroutine_Run_Coroutine(Coroutine *cor, void *value)
994
995(returns)
996: any problem, or `Coroutine_OK`
997
998cor
999: The Coroutine to run.
1000
1001value
1002: The value to pass to the Coroutine's `start` routine.
1003
1004Run 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, and the coroutine system must be started to call this.
1005
1006##### Coroutine_Err Coroutine_Run(size_t size, Coroutine_Start start, void *value, void **result)
1007
1008(returns)
1009: `Coroutine_OK` or any problem
1010
1011size
1012: The stack size to give to the Corotuine.
1013
1014start
1015: The routine to start the Coroutine.
1016
1017value
1018: The value to pass to `start()`.
1019
1020result
1021: Where to store the return value from `start(value)`. This may be `NULL`.
1022
1023`start(value)` is called from within a coroutine and its value returned in `*result`.
1024If this completes without any failure, `false` is returned, otherwise, typically
1025because `Coroutine_New()` returned `NULL`, `true` is returned. `result` may be `NULL` if you don't
1026need the resturn value from `start()`.
1027When the coroutine system is active - you are already running in a coroutine - `start(value)`
1028is simply called and its result returned in `*result`. When the Coroutine system is not running,
1029`Coroutine_Run()` starts it, creates a `Coroutine` and runs that Coroutine to call `start(calue)`
1030and return value is returned in `*result`, then stops the Coroutine system. If you need to force
1031a new Coroutine to be created, with a particular stack size to call `start(value)`, then use
1032`Coroutine_Chain()` instead.
1033
1034The total stack allowed for all coroutines running on any thread is the size of the call stack on that thread.
1035
1036##### void Coroutine_Delete(Coroutine *cor)
1037
1038cor
1039: The Coroutine to delete.
1040
1041Use `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.
1042
1043##### Coroutine_Err Coroutine_Continue(Coroutine *cor, void *value, bool early)
1044
1045(returns)
1046: `Coroutine_OK` or any error.
1047
1048cor
1049: The Coroutine to continue.
1050
1051value
1052: The value to return from `cor`'s yield function.
1053
1054early
1055: Whether to continue `cor` early (`true`), or late (`false`). Early means before other Coroutines which are waiting
1056to be called, whereas late means after them.
1057
1058Continue 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.
1059
1060##### void *Coroutine_Yield(void *value, Coroutine_YieldCallback on_yield, void *this)
1061
1062value
1063: The value to yield fropm the coroutine.
1064
1065on_yield
1066: A callback to be called once this Coroutine has yielded, but before another one has been continued.
1067
1068this
1069: The parameter to pass to `on_yield`.
1070
1071Yield `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()`.
1072
1073##### void *Coroutine_GetValue(Coroutine *cor)
1074
1075(returns)
1076: The Coroutine's value - the last yielded or returned value.
1077
1078cor
1079: The Coroutine to query.
1080
1081Return the `Coroutine`'s value - the value last yielded, or returned by its `start` routine.
1082
1083##### Coroutine *Coroutine_GetActive()
1084
1085(returns)
1086: The currently active Coroutine.
1087
1088Return whihc coroutine is currently running, ie the caller's `Coroutine`.
1089
1090##### bool Coroutine_IsRunning(Coroutine *cor)
1091
1092(returns)
1093: Whether `cor` is running - it's the active coroutine or waiting to be continued.
1094
1095cor
1096: The Coroutine to query.
1097
1098Return 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.
1099
1100##### bool Coroutine_IsComplete(Coroutine *cor)
1101
1102(returns)
1103: Whether `cor` is complete, ie has returned from `start()`./
1104
1105cor
1106: The Coroutine to query.
1107
1108Return whether the given coroutine is complete - is has returned from its `start` function.
1109
1110##### intptr_t Coroutine_GetStackHeadroom()
1111
1112(returns)
1113: The amount of stack headroom.
1114
1115Return 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.
1116
1117##### bool Coroutine_CanStartCoroutine(size_t size)
1118
1119(returns)
1120: Whether a Coroutine with the given amount of stack could be created.
1121
1122size
1123: The amount of stack in the Coroutine we might want to create.
1124
1125Return whether the coroutine system can start a new coroutine. This check can only be done with the coroutine system active (currently running
1126a 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
1127stack use `Coroutine_SetStackLimit()`
1128
1129##### void *Coroutine_GetStackHWM(void)
1130
1131(returns)
1132: The lowest address where the active Coroutine's stack has grown to ever.
1133
1134Find 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:
1135
1136 #!C
1137 Coroutine_ClearStackForHWM();
1138 char *before = (char *)Coroutine_GetStackHWM();
1139 // do the thing you want to measure here
1140 char *after = (char *)Coroutine_GetStackHWM();
1141 intptr_t amount_used = before - after;
1142
1143##### void Coroutine_ClearStackForHWM(void)
1144
1145Fill 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:
1146
1147 #!C
1148 Coroutine_ClearStackForHWM();
1149 char *before = (char *)Coroutine_GetStackHWM();
1150 // do the thing you want to measure here
1151 char *after = (char *)Coroutine_GetStackHWM();
1152 intptr_t amount_used = before - after;
1153
1154##### void *Coroutine_GetCStackTop()
1155
1156(returns)
1157: Where the Coroutine system has reached in the C stack.
1158
1159Return an address which is near to the top of used C stack.
1160
1161##### Coroutine_Err Coroutine_Chain(size_t size, Coroutine_Start start, void *value, void **result)
1162
1163(returns)
1164: Whether there was a problem. `Coroutine_OK` - `start(value)` was run; an error - there was a problem.
1165
1166size
1167: The amount of stack to give the chained Coroutine.
1168
1169start
1170: The entry point ot the chained Coroutine.
1171
1172value
1173: The value to pass to `start()`
1174
1175result
1176: Where to store the return value from `start(value)`. This may be `NULL`.
1177
1178Run `start` with `value` on a new coroutine, and return its return value in `*result`. `result`
1179may be NULL. `Coroutine_Run()` returns `false` if nothing fails, and `true` if something went wrong,
1180usually when `Coroutine_New()` ran out of stack. `stack_size` is the amount of stack made available
1181to the chained Coroutine.
1182It is expected that `Coroutine_Chain()` will be used when your coroutine is running short
1183of stack - it is not an alternative to `Coroutine_Run()`.
1184
1185##### void Coroutine_Dump_()
1186
1187*Do not use this function in production code*
1188
1189This prints the current state of the Coroutine system. It is used for development, and is not part of the official interface.
1190