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