37
68
81 86
Variable stack Coroutines WIP
on 3:07 PM Dec 23 2025
67
68
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
#include "task.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <math.h>
#include <string.h>
#include "timespec_utils.h"
_Cor_thread_local Task *current_task;
static void _Task_SetResult(
Future *fut,
bool canceled,
void *res
){
(void)fut;
(void)canceled;
(void)res;
// only the task can set it's future's result
assert(false);
}
Future_vfptrs_t Task_vfptrs = {
(void(*)(Future *fut))&Task_dtor,
&_Future_Await,
&_Task_SetResult,
};
static void *Task_entry(void *me){
Task *tsk = (Task *)me;
void *res = NULL;
assert(current_task == NULL);
current_task = tsk;
bool canceled = tsk->entry(tsk->param, &res);
current_task = NULL;
_Future_SetResult(&tsk->base, canceled, res);
return res;
}
void Task_ctor(
Task *tsk,
Task_Entry entry,
void *param
){
assert(Coroutine_IsStarted());
Future_ctor(&tsk->base);
tsk->base.vfptrs = &Task_vfptrs;
tsk->entry = entry;
tsk->param = param;
tsk->cor = Coroutine_New(Task_entry);
tsk->awaiting_future = NULL;
tsk->canceled = false;
tsk->cancel_value = NULL;
if (current_task){
Coroutine_Continue(tsk->cor, tsk, false);
}
}
void Task_dtor(
Task *tsk
){
Coroutine_Delete(tsk->cor);
Future_dtor(&tsk->base);
}
Task *Task_New(
Task_Entry entry,
void *param
){
Task *tsk = malloc(sizeof(Task));
Task_ctor(tsk, entry, param);
return tsk;
}
void Task_Delete(
Task *tsk
){
Future_Delete(&tsk->base);
}
void Task_Cancel(
Task *tsk,
void *cancel_value
){
if (!tsk->canceled){
tsk->canceled = true;
tsk->cancel_value = cancel_value;
Future *awaiting_future = tsk->awaiting_future;
if (awaiting_future){
Future_SetResult(awaiting_future, true, NULL);
}
}
}
bool Task_Run(Task_Entry start, void *value, void **res){
assert(current_task == NULL);
Task tsk;
Task_ctor(&tsk, start, value);
Coroutine_Run_Coroutine(tsk.cor, &tsk);
bool canceled = Future_GetResult(&tsk.base, res);
Task_dtor(&tsk);
return canceled;
}
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
#include "task.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <math.h>
#include <string.h>
#include "timespec_utils.h"
_Cor_thread_local Task *current_task;
static void _Task_SetResult(
Future *fut,
bool canceled,
void *res
){
(void)fut;
(void)canceled;
(void)res;
// only the task can set it's future's result
assert(false);
}
Future_vfptrs_t Task_vfptrs = {
(void(*)(Future *fut))&Task_dtor,
&_Future_Await,
&_Task_SetResult,
};
static void *Task_entry(void *me){
Task *tsk = (Task *)me;
void *res = NULL;
assert(current_task == NULL);
current_task = tsk;
bool canceled = tsk->entry(tsk->param, &res);
current_task = NULL;
_Future_SetResult(&tsk->base, canceled, res);
return res;
}
void Task_ctor(
Task *tsk,
size_t stack_size,
Task_Entry entry,
void *param
){
assert(Coroutine_IsStarted());
Future_ctor(&tsk->base);
tsk->base.vfptrs = &Task_vfptrs;
tsk->entry = entry;
tsk->param = param;
tsk->cor = Coroutine_New(stack_size, Task_entry);
tsk->awaiting_future = NULL;
tsk->canceled = false;
tsk->cancel_value = NULL;
if (current_task){
Coroutine_Continue(tsk->cor, tsk, false);
}
}
void Task_dtor(
Task *tsk
){
Coroutine_Delete(tsk->cor);
Future_dtor(&tsk->base);
}
Task *Task_New(
size_t stack_size,
Task_Entry entry,
void *param
){
Task *tsk = malloc(sizeof(Task));
Task_ctor(tsk, stack_size, entry, param);
return tsk;
}
void Task_Delete(
Task *tsk
){
Future_Delete(&tsk->base);
}
void Task_Cancel(
Task *tsk,
void *cancel_value
){
if (!tsk->canceled){
tsk->canceled = true;
tsk->cancel_value = cancel_value;
Future *awaiting_future = tsk->awaiting_future;
if (awaiting_future){
Future_SetResult(awaiting_future, true, NULL);
}
}
}
bool Task_Run(size_t stack_size, Task_Entry start, void *value, void **res){
assert(current_task == NULL);
Task tsk;
Task_ctor(&tsk, stack_size, start, value);
Coroutine_Run_Coroutine(tsk.cor, &tsk);
bool canceled = Future_GetResult(&tsk.base, res);
Task_dtor(&tsk);
return canceled;
}