9 months ago |
37 |
1 |
#include "task.h" | ||
2 |
#include <assert.h> | ||||
3 |
#include <stdio.h> | ||||
4 |
#include <stdlib.h> | ||||
5 |
#include <time.h> | ||||
6 |
#include <errno.h> | ||||
7 |
#include <math.h> | ||||
8 |
#include <string.h> | ||||
9 |
#include "timespec_utils.h" | ||||
4 hours ago |
10 |
#include "coroutine_names_def.h" | |||
9 months ago |
37 |
11 |
|||
12 |
|||||
13 |
_Cor_thread_local Task *current_task; | ||||
14 |
|||||
15 |
|||||
1 weeks ago |
16 |
static void | |||
17 |
_Task_SetResult( | ||||
9 months ago |
37 |
18 |
Future *fut, | ||
19 |
bool canceled, | ||||
20 |
void *res | ||||
21 |
){ | ||||
22 |
(void)fut; | ||||
23 |
(void)canceled; | ||||
24 |
(void)res; | ||||
25 |
// only the task can set it's future's result | ||||
26 |
assert(false); | ||||
27 |
} | ||||
28 |
|||||
29 |
|||||
30 |
Future_vfptrs_t Task_vfptrs = { | ||||
31 |
(void(*)(Future *fut))&Task_dtor, | ||||
32 |
&_Future_Await, | ||||
33 |
&_Task_SetResult, | ||||
34 |
}; | ||||
35 |
|||||
36 |
|||||
1 weeks ago |
37 |
static void * | |||
38 |
Task_entry(void *me){ | ||||
9 months ago |
37 |
39 |
Task *tsk = (Task *)me; | ||
40 |
void *res = NULL; | ||||
41 |
assert(current_task == NULL); | ||||
42 |
current_task = tsk; | ||||
43 |
bool canceled = tsk->entry(tsk->param, &res); | ||||
44 |
current_task = NULL; | ||||
45 |
_Future_SetResult(&tsk->base, canceled, res); | ||||
46 |
return res; | ||||
47 |
} | ||||
48 |
|||||
49 |
|||||
1 weeks ago |
50 |
static void | |||
51 |
Task_ctor_( | ||||
9 months ago |
37 |
52 |
Task *tsk, | ||
1 weeks ago |
53 |
Coroutine *cor | |||
9 months ago |
37 |
54 |
){ | ||
4 hours ago |
55 |
assert(Coroutine_IsStarted()); | |||
9 months ago |
37 |
56 |
Future_ctor(&tsk->base); | ||
57 |
tsk->base.vfptrs = &Task_vfptrs; | ||||
1 weeks ago |
58 |
tsk->cor = cor; | |||
59 |
tsk->cor_owned = false; | ||||
9 months ago |
37 |
60 |
tsk->awaiting_future = NULL; | ||
61 |
tsk->canceled = false; | ||||
62 |
tsk->cancel_value = NULL; | ||||
63 |
if (current_task){ | ||||
4 hours ago |
64 |
Coroutine_Continue(tsk->cor, tsk, false); | |||
9 months ago |
37 |
65 |
} | ||
66 |
} | ||||
67 |
|||||
68 |
|||||
1 weeks ago |
69 |
void | |||
70 |
Task_ctor( | ||||
71 |
Task *tsk, | ||||
72 |
size_t min_stack, | ||||
73 |
size_t min_stack_headroom, | ||||
74 |
Task_Entry entry, | ||||
75 |
void *param | ||||
76 |
){ | ||||
4 hours ago |
77 |
assert(Coroutine_IsStarted()); | |||
78 |
Task_ctor_(tsk, Coroutine_New(min_stack, min_stack_headroom, Task_entry)); | ||||
1 weeks ago |
79 |
tsk->cor_owned = true; | |||
80 |
tsk->entry = entry; | ||||
81 |
tsk->param = param; | ||||
82 |
if (current_task){ | ||||
4 hours ago |
83 |
Coroutine_Continue(tsk->cor, tsk, false); | |||
1 weeks ago |
84 |
} | |||
85 |
} | ||||
86 |
|||||
87 |
|||||
88 |
void | ||||
89 |
Task_dtor( | ||||
9 months ago |
37 |
90 |
Task *tsk | ||
91 |
){ | ||||
1 weeks ago |
92 |
if (tsk->cor_owned){ | |||
4 hours ago |
93 |
Coroutine_Delete(tsk->cor); | |||
1 weeks ago |
94 |
} | |||
9 months ago |
37 |
95 |
Future_dtor(&tsk->base); | ||
96 |
} | ||||
97 |
|||||
98 |
|||||
1 weeks ago |
99 |
Task * | |||
100 |
Task_New( | ||||
101 |
size_t min_stack, | ||||
102 |
size_t min_stack_headroom, | ||||
9 months ago |
37 |
103 |
Task_Entry entry, | ||
104 |
void *param | ||||
105 |
){ | ||||
106 |
Task *tsk = malloc(sizeof(Task)); | ||||
1 weeks ago |
107 |
Task_ctor(tsk, min_stack, min_stack_headroom, entry, param); | |||
9 months ago |
37 |
108 |
return tsk; | ||
109 |
} | ||||
110 |
|||||
111 |
|||||
1 weeks ago |
112 |
void | |||
113 |
Task_Delete( | ||||
9 months ago |
37 |
114 |
Task *tsk | ||
115 |
){ | ||||
116 |
Future_Delete(&tsk->base); | ||||
117 |
} | ||||
118 |
|||||
119 |
|||||
1 weeks ago |
120 |
void | |||
121 |
Task_Cancel( | ||||
9 months ago |
37 |
122 |
Task *tsk, | ||
123 |
void *cancel_value | ||||
124 |
){ | ||||
125 |
if (!tsk->canceled){ | ||||
126 |
tsk->canceled = true; | ||||
127 |
tsk->cancel_value = cancel_value; | ||||
128 |
Future *awaiting_future = tsk->awaiting_future; | ||||
129 |
if (awaiting_future){ | ||||
130 |
Future_SetResult(awaiting_future, true, NULL); | ||||
131 |
} | ||||
132 |
} | ||||
133 |
} | ||||
134 |
|||||
135 |
|||||
4 months ago |
136 |
struct Task_Run_Params { | |||
1 weeks ago |
137 |
size_t min_stack; | |||
138 |
size_t min_stack_headroom; | ||||
4 months ago |
139 |
Task_Entry start; | |||
140 |
void *value; | ||||
141 |
void **res; | ||||
142 |
}; | ||||
143 |
|||||
1 weeks ago |
144 |
static Coroutine_Err | |||
145 |
Task_Runner( | ||||
146 |
void *_params, | ||||
147 |
Coroutine *root | ||||
148 |
){ | ||||
4 months ago |
149 |
struct Task_Run_Params *params = (struct Task_Run_Params *)_params; | |||
150 |
|||||
1 weeks ago |
151 |
Task roottsk; | |||
152 |
Task_ctor_(&roottsk, root); | ||||
153 |
current_task = &roottsk; | ||||
154 |
Task childtask; | ||||
155 |
Task_ctor(&childtask, params->min_stack, params->min_stack_headroom, params->start, params->value); | ||||
156 |
Coroutine_Err err = Task_Await(&childtask, params->res); | ||||
157 |
Task_dtor(&childtask); | ||||
158 |
current_task = NULL; | ||||
159 |
Task_dtor(&roottsk); | ||||
4 months ago |
160 |
return err; | |||
9 months ago |
37 |
161 |
} | ||
4 months ago |
162 |
||||
1 weeks ago |
163 |
bool | |||
164 |
Task_Run( | ||||
165 |
size_t min_stack, | ||||
166 |
size_t min_stack_headroom, | ||||
167 |
Task_Entry start, | ||||
168 |
void *value, | ||||
169 |
void **res | ||||
170 |
){ | ||||
4 months ago |
171 |
if (current_task){ | |||
172 |
return Coroutine_Err_SystemRunning; | ||||
173 |
} | ||||
1 weeks ago |
174 |
struct Task_Run_Params params = {min_stack, min_stack_headroom, start, value, res}; | |||
4 hours ago |
175 |
return Coroutine_RunSystem(0, COROUTINE_STARTUP_STACK_SIZE, Task_Runner, ¶ms); | |||
4 months ago |
176 |
} | |||
4 hours ago |
177 |
#include "coroutine_names_undef.h" | |||
178 |