0 branches 0 tags
45 46
47
48 49
extern declare all functions
on 2:10 PM Oct 21 2025
trunk/include/asleep.h
46
47
1
2
3
4
5
6
7
8
9
10
11
#ifndef ASLEEP_H
#define ASLEEP_H
#include <stdbool.h>
#include "task.h"
void ASleep_StartSystem();
bool ASleep(float delay, void **value);
void ASleep_StopSystem();
#endif
1
2
3
4
5
6
7
8
9
10
11
#ifndef ASLEEP_H
#define ASLEEP_H
#include <stdbool.h>
#include "task.h"
extern void ASleep_StartSystem();
extern bool ASleep(float delay, void **value);
extern void ASleep_StopSystem();
#endif
trunk/include/cor_platform.h
46
47
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#ifndef COR_PLATFORM_H
#define COR_PLATFORM_H
// platform specific parts collected together
#include <stdbool.h>
#include <pthread.h>
#include <errno.h>
// inspired by CPython to achieve platform indenpendence for thread local variables
#ifdef thread_local
#define _Cor_thread_local thread_local
#elif __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__)
#define _Cor_thread_local _Thread_local
#elif defined(_MSC_VER) /* AKA NT_THREADS */
#define _Cor_thread_local __declspec(thread)
#elif defined(__GNUC__) /* includes clang */
#define _Cor_thread_local __thread
#else
#define _Cor_thread_local
#endif
// Non-reentrant Mutexes
typedef struct _Cor_Mutex {
pthread_mutex_t mut;
} _Cor_Mutex;
void _Cor_Mutex_ctor(_Cor_Mutex *);
void _Cor_Mutex_dtor(_Cor_Mutex *);
void _Cor_Mutex_Lock(_Cor_Mutex *);
void _Cor_Mutex_Unlock(_Cor_Mutex *);
// The 'now' to use for _Cor_Semaphore_Wait, in ns.
int64_t _Cor_Realtime_Now();
typedef struct _Cor_Semaphore {
pthread_mutex_t mut;
pthread_cond_t cond;
unsigned count;
} _Cor_Semaphore;
void _Cor_Semaphore_ctor(_Cor_Semaphore *sem);
void _Cor_Sempahore_dtor(_Cor_Semaphore *sem);
// timeout_when < 0 means 'wait forever'
// Returns true for success, false for timeout
bool _Cor_Semaphore_Wait(_Cor_Semaphore *sem, int64_t timeout_when);
void _Cor_Semaphore_Signal(_Cor_Semaphore *sem);
typedef struct _Cor_Thread {
pthread_t th;
bool joined;
} _Cor_Thread;
void _Cor_Thread_ctor(_Cor_Thread *, void *(*)(void *), void *);
void _Cor_Thread_dtor(_Cor_Thread *);
void *_Cor_Thread_Join(_Cor_Thread *);
#endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#ifndef COR_PLATFORM_H
#define COR_PLATFORM_H
// platform specific parts collected together
#include <stdbool.h>
#include <pthread.h>
#include <errno.h>
// inspired by CPython to achieve platform indenpendence for thread local variables
#ifdef thread_local
#define _Cor_thread_local thread_local
#elif __STDC_VERSION__ >= 201112L && !defined(__STDC_NO_THREADS__)
#define _Cor_thread_local _Thread_local
#elif defined(_MSC_VER) /* AKA NT_THREADS */
#define _Cor_thread_local __declspec(thread)
#elif defined(__GNUC__) /* includes clang */
#define _Cor_thread_local __thread
#else
#define _Cor_thread_local
#endif
// Non-reentrant Mutexes
typedef struct _Cor_Mutex {
pthread_mutex_t mut;
} _Cor_Mutex;
extern void _Cor_Mutex_ctor(_Cor_Mutex *);
extern void _Cor_Mutex_dtor(_Cor_Mutex *);
extern void _Cor_Mutex_Lock(_Cor_Mutex *);
extern void _Cor_Mutex_Unlock(_Cor_Mutex *);
// The 'now' to use for _Cor_Semaphore_Wait, in ns.
extern int64_t _Cor_Realtime_Now();
typedef struct _Cor_Semaphore {
pthread_mutex_t mut;
pthread_cond_t cond;
unsigned count;
} _Cor_Semaphore;
extern void _Cor_Semaphore_ctor(_Cor_Semaphore *sem);
extern void _Cor_Sempahore_dtor(_Cor_Semaphore *sem);
// timeout_when < 0 means 'wait forever'
// Returns true for success, false for timeout
extern bool _Cor_Semaphore_Wait(_Cor_Semaphore *sem, int64_t timeout_when);
extern void _Cor_Semaphore_Signal(_Cor_Semaphore *sem);
typedef struct _Cor_Thread {
pthread_t th;
bool joined;
} _Cor_Thread;
extern void _Cor_Thread_ctor(_Cor_Thread *, void *(*)(void *), void *);
extern void _Cor_Thread_dtor(_Cor_Thread *);
extern void *_Cor_Thread_Join(_Cor_Thread *);
#endif
trunk/include/coroutine.h
46
47
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#ifndef COROUTINE_H
#define COROUTINE_H
#include <stdbool.h>
///////////////////////////////////////////////////////////////////////////////
// Coroutine
//
// Coroutines for C, based on setjmp/longjmp.
// Thread safe - each thread has its own coroutine system
// Coroutines are cooperatively scheduled
// Coroutines have their own stack (currently 16K each)
// A coroutine can be continued, queried, or deleted on a different thread.
//
// Usage:
// Coroutine_StartSystem(); // call once per thread before using coroutines
// Coroutine *co = Coroutine_New(start_function);
// void *result = Coroutine_Run(co, initial_value);
// Coroutine_Delete(co);
// Coroutine_StopSystem(); // call once per thread when done with coroutines
//
// Inside the coroutine function:
// void *value = Coroutine_Yield(yield_value, on_yield, this);
// ...
// return return_value;
//
// To create a coroutine:
// Coroutine *co = Coroutine_New(start_function);
// To start or continue a coroutine:
// void *result = Coroutine_Continue(co, value, early);
// // early=true puts the coroutine at the head of the run queue
// // early=false puts the coroutine at the tail of the run queue
// To yield from inside a coroutine:
// void *value = Coroutine_Yield(yield_value, on_yield, this);
// // on_yield is called before the next coroutine is run
// // 'this' is passed to on_yield as its parameter
// // value is the value passed to Coroutine_Continue
// To delete a coroutine:
// Coroutine_Delete(co);
// To get the value yielded from, or returned by a corotuine:
// void *value = Coroutine_GetValue(co);
// To get the currently running coroutine (NULL if none):
// Coroutine *co = Coroutine_GetActive();
// To check if a coroutine is currently running:
// bool running = Coroutine_IsRunning(co);
//
// Notes:
// Coroutine is not expected to be used directly, but as a foundation for
// higher level constructs such as Generators, Async, etc.
//
///////////////////////////////////////////////////////////////////////////////
// The stack is used as follows:
// +------------------+ <- stack top
// | coroutine header | <- more claimed as needed in Coroutine_New
// +------------------+ <-
// | coroutine stack | <-
// +------------------+ <-
// | coroutine header |
// +------------------+
// | coroutine stack |
// +------------------+
// | coroutine header |
// +------------------+
// | coroutine stack |
// +------------------+
// | coroutine header |
// +------------------+
// | coroutine stack |
// +------------------+
// | coroutine header |
// +------------------+
// | startup space | <- set aside by Coroutine_StartSystem
// +------------------+
// | caller | <- This calls Coroutine_StartSystem etc
// +------------------+
// | used stack |
// +------------------+ <- stack bottom
// Each coroutine has this much stack:
#ifndef COROUTINE_STACK_SIZE
#define COROUTINE_STACK_SIZE 65536
#endif
// When Coroutine is started, an amount of stack is set aside to give
// the caller of Coroutine_StartSystem a bit of room to work before calling
// Coroutine_Run(), that is this amount:
#ifndef COROUTINE_STARTUP_STACK_SIZE
#define COROUTINE_STARTUP_STACK_SIZE 4096
#endif
// Returned by Coroutine_StopSystem(), this summarises the coroutine session
typedef struct Coroutine_Report {
unsigned coroutines_created;
unsigned coroutines_pool_size;
unsigned lowest_headroom;
} Coroutine_Report;
typedef struct Coroutine Coroutine;
typedef void (*Coroutine_YieldCallback)(void *me);
typedef void *(*Coroutine_Start)(void *);
void Coroutine_StartSystem();
Coroutine_Report Coroutine_StopSystem();
Coroutine *Coroutine_New(Coroutine_Start start);
void Coroutine_Run_Coroutine(Coroutine *cor, void *value);
void *Coroutine_Run(Coroutine_Start start, void *value);
void Coroutine_Delete(Coroutine *cor);
void Coroutine_Continue(Coroutine *cor, void *value, bool early);
void *Coroutine_Yield(void *value, Coroutine_YieldCallback on_yield, void *me);
void *Coroutine_GetValue(Coroutine *cor);
Coroutine *Coroutine_GetActive();
int Coroutine_GetStackHeadroom();
bool Coroutine_HasCoroutinesInFreePool();
void *Coroutine_GetCStackTop();
void *Coroutine_Chain(Coroutine_Start start, void *value);
bool Coroutine_IsStarted();
bool Coroutine_IsRunning(Coroutine *cor);
#endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#ifndef COROUTINE_H
#define COROUTINE_H
#include <stdbool.h>
///////////////////////////////////////////////////////////////////////////////
// Coroutine
//
// Coroutines for C, based on setjmp/longjmp.
// Thread safe - each thread has its own coroutine system
// Coroutines are cooperatively scheduled
// Coroutines have their own stack (currently 16K each)
// A coroutine can be continued, queried, or deleted on a different thread.
//
// Usage:
// Coroutine_StartSystem(); // call once per thread before using coroutines
// Coroutine *co = Coroutine_New(start_function);
// void *result = Coroutine_Run(co, initial_value);
// Coroutine_Delete(co);
// Coroutine_StopSystem(); // call once per thread when done with coroutines
//
// Inside the coroutine function:
// void *value = Coroutine_Yield(yield_value, on_yield, this);
// ...
// return return_value;
//
// To create a coroutine:
// Coroutine *co = Coroutine_New(start_function);
// To start or continue a coroutine:
// void *result = Coroutine_Continue(co, value, early);
// // early=true puts the coroutine at the head of the run queue
// // early=false puts the coroutine at the tail of the run queue
// To yield from inside a coroutine:
// void *value = Coroutine_Yield(yield_value, on_yield, this);
// // on_yield is called before the next coroutine is run
// // 'this' is passed to on_yield as its parameter
// // value is the value passed to Coroutine_Continue
// To delete a coroutine:
// Coroutine_Delete(co);
// To get the value yielded from, or returned by a corotuine:
// void *value = Coroutine_GetValue(co);
// To get the currently running coroutine (NULL if none):
// Coroutine *co = Coroutine_GetActive();
// To check if a coroutine is currently running:
// bool running = Coroutine_IsRunning(co);
//
// Notes:
// Coroutine is not expected to be used directly, but as a foundation for
// higher level constructs such as Generators, Async, etc.
//
///////////////////////////////////////////////////////////////////////////////
// The stack is used as follows:
// +------------------+ <- stack top
// | coroutine header | <- more claimed as needed in Coroutine_New
// +------------------+ <-
// | coroutine stack | <-
// +------------------+ <-
// | coroutine header |
// +------------------+
// | coroutine stack |
// +------------------+
// | coroutine header |
// +------------------+
// | coroutine stack |
// +------------------+
// | coroutine header |
// +------------------+
// | coroutine stack |
// +------------------+
// | coroutine header |
// +------------------+
// | startup space | <- set aside by Coroutine_StartSystem
// +------------------+
// | caller | <- This calls Coroutine_StartSystem etc
// +------------------+
// | used stack |
// +------------------+ <- stack bottom
// Each coroutine has this much stack:
#ifndef COROUTINE_STACK_SIZE
#define COROUTINE_STACK_SIZE 65536
#endif
// When Coroutine is started, an amount of stack is set aside to give
// the caller of Coroutine_StartSystem a bit of room to work before calling
// Coroutine_Run(), that is this amount:
#ifndef COROUTINE_STARTUP_STACK_SIZE
#define COROUTINE_STARTUP_STACK_SIZE 4096
#endif
// Returned by Coroutine_StopSystem(), this summarises the coroutine session
typedef struct Coroutine_Report {
unsigned coroutines_created;
unsigned coroutines_pool_size;
unsigned lowest_headroom;
} Coroutine_Report;
typedef struct Coroutine Coroutine;
typedef void (*Coroutine_YieldCallback)(void *me);
typedef void *(*Coroutine_Start)(void *);
extern void Coroutine_StartSystem();
extern Coroutine_Report Coroutine_StopSystem();
extern Coroutine *Coroutine_New(Coroutine_Start start);
extern void Coroutine_Run_Coroutine(Coroutine *cor, void *value);
extern void *Coroutine_Run(Coroutine_Start start, void *value);
extern void Coroutine_Delete(Coroutine *cor);
extern void Coroutine_Continue(Coroutine *cor, void *value, bool early);
extern void *Coroutine_Yield(void *value, Coroutine_YieldCallback on_yield, void *me);
extern void *Coroutine_GetValue(Coroutine *cor);
extern Coroutine *Coroutine_GetActive();
extern int Coroutine_GetStackHeadroom();
extern bool Coroutine_HasCoroutinesInFreePool();
extern void *Coroutine_GetCStackTop();
extern void *Coroutine_Chain(Coroutine_Start start, void *value);
extern bool Coroutine_IsStarted();
extern bool Coroutine_IsRunning(Coroutine *cor);
#endif
trunk/include/future.h
46
47
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#ifndef FUTURE_H
#define FUTURE_H
#include <stdbool.h>
typedef struct Future Future;
typedef struct Future_vfptrs_t {
void (*dtor)(Future *);
void (*await)(Future *);
void (*set_result)(Future *, bool, void *);
} Future_vfptrs_t;
void _Future_Await(Future *fut);
void _Future_SetResult(Future *fut, bool canceled, void *res);
// Notified when a Future is done (has a result or is canceled)
typedef void (*Future_Watcher)(void *me, Future *fut);
void Future_ctor(Future *fut);
Future *Future_New();
void Future_dtor(Future *fut);
void Future_Delete(Future *fut);
void Future_SetResult(Future *fut, bool canceled, void *value);
bool Future_GetResult(Future *fut, void **res);
void Future_AddWatcher(Future *fut, Future_Watcher watcher, void *me);
void Future_RemoveWatcher(Future *fut, Future_Watcher watcher, void *me);
bool Future_Await(Future *fut, void **res);
#include "future.def.h"
#endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#ifndef FUTURE_H
#define FUTURE_H
#include <stdbool.h>
typedef struct Future Future;
typedef struct Future_vfptrs_t {
void (*dtor)(Future *);
void (*await)(Future *);
void (*set_result)(Future *, bool, void *);
} Future_vfptrs_t;
extern void _Future_Await(Future *fut);
extern void _Future_SetResult(Future *fut, bool canceled, void *res);
// Notified when a Future is done (has a result or is canceled)
typedef void (*Future_Watcher)(void *me, Future *fut);
extern void Future_ctor(Future *fut);
extern Future *Future_New();
extern void Future_dtor(Future *fut);
extern void Future_Delete(Future *fut);
extern void Future_SetResult(Future *fut, bool canceled, void *value);
extern bool Future_GetResult(Future *fut, void **res);
extern void Future_AddWatcher(Future *fut, Future_Watcher watcher, void *me);
extern void Future_RemoveWatcher(Future *fut, Future_Watcher watcher, void *me);
extern bool Future_Await(Future *fut, void **res);
#include "future.def.h"
#endif
trunk/include/generator.h
46
47
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#ifndef GENERATOR_H
#define GENERATOR_H
#include "coroutine.h"
#include <stdbool.h>
typedef enum Generator_State {
Generator_Running,
Generator_Deleting,
Generator_Complete
} Generator_State;
typedef struct Generator {
Coroutine *coroutine;
Coroutine *caller;
void *(*start)(void *);
void *param;
Generator_State state;
} Generator;
void Generator_ctor(Generator *gen, void *(*start)(void *), void *param);
Generator *Generator_New(void *(*)(void *), void *);
void Generator_dtor(Generator *gen);
void Generator_Delete(Generator *);
// Returns true if generator yielded a value, false if generator is complete
// *value is set to generator's value (yield / return value from exit)
bool Generator_Next(Generator *, void **value);
// Yield a value from the generator
// Returns true if generator should continue, false for generator to exit PDQ
bool Generator_Yield(void *);
#endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#ifndef GENERATOR_H
#define GENERATOR_H
#include "coroutine.h"
#include <stdbool.h>
typedef enum Generator_State {
Generator_Running,
Generator_Deleting,
Generator_Complete
} Generator_State;
typedef struct Generator {
Coroutine *coroutine;
Coroutine *caller;
void *(*start)(void *);
void *param;
Generator_State state;
} Generator;
extern void Generator_ctor(Generator *gen, void *(*start)(void *), void *param);
extern Generator *Generator_New(void *(*)(void *), void *);
extern void Generator_dtor(Generator *gen);
extern void Generator_Delete(Generator *);
// Returns true if generator yielded a value, false if generator is complete
// *value is set to generator's value (yield / return value from exit)
extern bool Generator_Next(Generator *, void **value);
// Yield a value from the generator
// Returns true if generator should continue, false for generator to exit PDQ
extern bool Generator_Yield(void *);
#endif
trunk/include/task.h
46
47
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#ifndef TASK_H
#define TASK_H
#include <stdbool.h>
#include "future.h"
#include "cor_platform.h"
typedef struct Task Task;
extern _Cor_thread_local Task *current_task;
typedef bool (*Task_Entry)(void *param, void **res);
void Task_ctor(Task *tsk, Task_Entry entry, void *param);
Task *Task_New(Task_Entry entry, void *param);
void Task_dtor(Task *tsk);
void Task_Delete(Task *tsk);
static inline bool Task_Await(Task *tsk, void **res);
void Task_Cancel(Task *tsk, void *cancel_value);
static inline bool Task_IsCanceled(Task *tsk);
static inline Future *Task_GetAwaitedFuture(Task *tsk);
bool Task_Run(Task_Entry start, void *value, void **res);
#include "task.def.h"
#endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#ifndef TASK_H
#define TASK_H
#include <stdbool.h>
#include "future.h"
#include "cor_platform.h"
typedef struct Task Task;
extern _Cor_thread_local Task *current_task;
typedef bool (*Task_Entry)(void *param, void **res);
extern void Task_ctor(Task *tsk, Task_Entry entry, void *param);
extern Task *Task_New(Task_Entry entry, void *param);
extern void Task_dtor(Task *tsk);
extern void Task_Delete(Task *tsk);
static inline bool Task_Await(Task *tsk, void **res);
extern void Task_Cancel(Task *tsk, void *cancel_value);
static inline bool Task_IsCanceled(Task *tsk);
static inline Future *Task_GetAwaitedFuture(Task *tsk);
extern bool Task_Run(Task_Entry start, void *value, void **res);
#include "task.def.h"
#endif