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