1 contributor
147 lines5.4 KB
Newer
Older
-
+
commited
{line.log.rev}
on
8 months ago
1
#ifndef COROUTINE_H
2
#define COROUTINE_H
3
9 months ago
2
4
#include <stdbool.h>
5 months ago
5
#include <stddef.h>
7 months ago
6
#include <stdint.h>
9 months ago
2
7
8 months ago
8
///////////////////////////////////////////////////////////////////////////////
9
// Coroutine
10
//
11
// Coroutines for C, based on setjmp/longjmp.
12
// Thread safe - each thread has its own coroutine system
13
// Coroutines are cooperatively scheduled
14
// Coroutines have their own stack (currently 16K each)
15
// A coroutine can be continued, queried, or deleted on a different thread.
16
//
17
// Usage:
18
// Coroutine_StartSystem(); // call once per thread before using coroutines
19
// Coroutine *co = Coroutine_New(start_function);
5 months ago
20
// void *result;
21
// if (Coroutine_Run(co, initial_value, &result)){}
22
// // Handle the failure
23
// |
8 months ago
24
// Coroutine_Delete(co);
25
// Coroutine_StopSystem(); // call once per thread when done with coroutines
26
//
27
// Inside the coroutine function:
28
// void *value = Coroutine_Yield(yield_value, on_yield, this);
29
// ...
30
// return return_value;
31
//
32
// To create a coroutine:
33
// Coroutine *co = Coroutine_New(start_function);
34
// To start or continue a coroutine:
35
// void *result = Coroutine_Continue(co, value, early);
36
// // early=true puts the coroutine at the head of the run queue
37
// // early=false puts the coroutine at the tail of the run queue
38
// To yield from inside a coroutine:
39
// void *value = Coroutine_Yield(yield_value, on_yield, this);
40
// // on_yield is called before the next coroutine is run
41
// // 'this' is passed to on_yield as its parameter
42
// // value is the value passed to Coroutine_Continue
43
// To delete a coroutine:
44
// Coroutine_Delete(co);
45
// To get the value yielded from, or returned by a corotuine:
46
// void *value = Coroutine_GetValue(co);
47
// To get the currently running coroutine (NULL if none):
48
// Coroutine *co = Coroutine_GetActive();
49
// To check if a coroutine is currently running:
50
// bool running = Coroutine_IsRunning(co);
51
//
52
// Notes:
53
// Coroutine is not expected to be used directly, but as a foundation for
54
// higher level constructs such as Generators, Async, etc.
55
//
56
///////////////////////////////////////////////////////////////////////////////
57
58
59
// The stack is used as follows:
6 months ago
60
//
61
// Note: the stack is assumed to grow downwards through memory
62
//
63
// (low memory)
64
//
65
// <- limit. When set this and lower memory addresses are assumed to be unavailable for stack use
66
// (- lowest address usable by the stack -)
67
// . .
68
// . .
69
// | coroutine stack |
8 months ago
70
// +------------------+
6 months ago
71
// | coroutine header | <- 'tip' coroutine (latest allocated Coroutine)
72
// +------------------+
8 months ago
73
// | coroutine stack |
74
// +------------------+
6 months ago
75
// | coroutine header | <- 'active' Coroutine (the one currently running - could be 'tip')
8 months ago
76
// +------------------+
77
// | coroutine stack |
78
// +------------------+
79
// | coroutine header |
80
// +------------------+
81
// | coroutine stack |
82
// +------------------+
83
// | coroutine header |
84
// +------------------+
85
// | startup space | <- set aside by Coroutine_StartSystem
86
// +------------------+
87
// | caller | <- This calls Coroutine_StartSystem etc
88
// +------------------+
89
// | used stack |
6 months ago
90
// +------------------+ <- stack 'bottom'; highest address used by the stack
91
// (high memory)
8 months ago
92
5 months ago
93
// No coroutine will ask for less stack than this
94
#ifndef COROUTINE_MINIMUM_STACK_SIZE
95
#define COROUTINE_MINIMUM_STACK_SIZE (4096 * sizeof(void *))
8 months ago
96
#endif
8 months ago
97
5 months ago
98
// Before Coroutine has New()'ed a Coroutine, this amount of stack
99
// is set aside for workings between the New() and Run():
8 months ago
100
#ifndef COROUTINE_STARTUP_STACK_SIZE
5 months ago
101
#define COROUTINE_STARTUP_STACK_SIZE (128 * sizeof(void *))
8 months ago
102
#endif
8 months ago
103
6 months ago
104
// When allocating space for a coroutine stack, fill it with guard pattern
105
// so that lowest_headroom in the Coroutine_Report can be worked out
106
#ifndef COROUTINE_RECORD_LOWEST_HEADROOM
107
#define COROUTINE_RECORD_LOWEST_HEADROOM 1
108
#endif
109
8 months ago
110
// Returned by Coroutine_StopSystem(), this summarises the coroutine session
111
typedef struct Coroutine_Report {
112
unsigned coroutines_created;
113
unsigned coroutines_pool_size;
5 months ago
114
size_t lowest_headroom;
115
size_t largest_stack;
8 months ago
116
} Coroutine_Report;
117
9 months ago
2
118
typedef struct Coroutine Coroutine;
119
8 months ago
120
typedef void (*Coroutine_YieldCallback)(void *me);
9 months ago
2
121
typedef void *(*Coroutine_Start)(void *);
122
7 months ago
123
extern void Coroutine_StartSystem(void);
6 months ago
124
extern void Coroutine_SetStackLimit(void *);
7 months ago
125
extern Coroutine_Report Coroutine_StopSystem(void);
5 months ago
126
extern Coroutine *Coroutine_New(size_t size, Coroutine_Start start);
7 months ago
127
extern void Coroutine_Run_Coroutine(Coroutine *cor, void *value);
5 months ago
128
extern bool Coroutine_Run(size_t size, Coroutine_Start start, void *value, void **result);
7 months ago
129
extern void Coroutine_Delete(Coroutine *cor);
130
extern void Coroutine_Continue(Coroutine *cor, void *value, bool early);
131
extern void *Coroutine_Yield(void *value, Coroutine_YieldCallback on_yield, void *me);
132
extern void *Coroutine_GetValue(Coroutine *cor);
7 months ago
133
extern Coroutine *Coroutine_GetActive(void);
7 months ago
134
extern intptr_t Coroutine_GetStackHeadroom(void);
6 months ago
135
extern void *Coroutine_GetStackHWM(void);
136
extern void Coroutine_ClearStackForHWM(void);
5 months ago
137
extern bool Coroutine_CanStartCoroutine(size_t size);
7 months ago
138
extern void *Coroutine_GetCStackTop(void);
5 months ago
139
extern bool Coroutine_Chain(size_t size, Coroutine_Start start, void *value, void **result);
7 months ago
140
extern bool Coroutine_IsStarted(void);
7 months ago
141
extern bool Coroutine_IsRunning(Coroutine *cor);
6 months ago
142
extern bool Coroutine_IsComplete(Coroutine *cor);
8 months ago
143
5 months ago
144
extern void _Coroutine_Dump(void);
145
8 months ago
146
#endif
147