8 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 |
|||||
15 |
static void _Task_SetResult( | ||||
16 |
Future *fut, | ||||
17 |
bool canceled, | ||||
18 |
void *res | ||||
19 |
){ | ||||
20 |
(void)fut; | ||||
21 |
(void)canceled; | ||||
22 |
(void)res; | ||||
23 |
// only the task can set it's future's result | ||||
24 |
assert(false); | ||||
25 |
} | ||||
26 |
|||||
27 |
|||||
28 |
Future_vfptrs_t Task_vfptrs = { | ||||
29 |
(void(*)(Future *fut))&Task_dtor, | ||||
30 |
&_Future_Await, | ||||
31 |
&_Task_SetResult, | ||||
32 |
}; | ||||
33 |
|||||
34 |
|||||
35 |
static void *Task_entry(void *me){ | ||||
36 |
Task *tsk = (Task *)me; | ||||
37 |
void *res = NULL; | ||||
38 |
assert(current_task == NULL); | ||||
39 |
current_task = tsk; | ||||
40 |
bool canceled = tsk->entry(tsk->param, &res); | ||||
41 |
current_task = NULL; | ||||
42 |
_Future_SetResult(&tsk->base, canceled, res); | ||||
43 |
return res; | ||||
44 |
} | ||||
45 |
|||||
46 |
|||||
47 |
void Task_ctor( | ||||
48 |
Task *tsk, | ||||
49 |
Task_Entry entry, | ||||
50 |
void *param | ||||
51 |
){ | ||||
52 |
assert(Coroutine_IsStarted()); | ||||
53 |
Future_ctor(&tsk->base); | ||||
54 |
tsk->base.vfptrs = &Task_vfptrs; | ||||
55 |
tsk->entry = entry; | ||||
56 |
tsk->param = param; | ||||
57 |
tsk->cor = Coroutine_New(Task_entry); | ||||
58 |
tsk->awaiting_future = NULL; | ||||
59 |
tsk->canceled = false; | ||||
60 |
tsk->cancel_value = NULL; | ||||
61 |
if (current_task){ | ||||
62 |
Coroutine_Continue(tsk->cor, tsk, false); | ||||
63 |
} | ||||
64 |
} | ||||
65 |
|||||
66 |
|||||
67 |
void Task_dtor( | ||||
68 |
Task *tsk | ||||
69 |
){ | ||||
70 |
Coroutine_Delete(tsk->cor); | ||||
71 |
Future_dtor(&tsk->base); | ||||
72 |
} | ||||
73 |
|||||
74 |
|||||
75 |
Task *Task_New( | ||||
76 |
Task_Entry entry, | ||||
77 |
void *param | ||||
78 |
){ | ||||
79 |
Task *tsk = malloc(sizeof(Task)); | ||||
80 |
Task_ctor(tsk, entry, param); | ||||
81 |
return tsk; | ||||
82 |
} | ||||
83 |
|||||
84 |
|||||
85 |
void Task_Delete( | ||||
86 |
Task *tsk | ||||
87 |
){ | ||||
88 |
Future_Delete(&tsk->base); | ||||
89 |
} | ||||
90 |
|||||
91 |
|||||
92 |
void Task_Cancel( | ||||
93 |
Task *tsk, | ||||
94 |
void *cancel_value | ||||
95 |
){ | ||||
96 |
if (!tsk->canceled){ | ||||
97 |
tsk->canceled = true; | ||||
98 |
tsk->cancel_value = cancel_value; | ||||
99 |
Future *awaiting_future = tsk->awaiting_future; | ||||
100 |
if (awaiting_future){ | ||||
101 |
Future_SetResult(awaiting_future, true, NULL); | ||||
102 |
} | ||||
103 |
} | ||||
104 |
} | ||||
105 |
|||||
106 |
|||||
107 |
bool Task_Run(Task_Entry start, void *value, void **res){ | ||||
108 |
assert(current_task == NULL); | ||||
109 |
Task tsk; | ||||
110 |
Task_ctor(&tsk, start, value); | ||||
111 |
Coroutine_Run_Coroutine(tsk.cor, &tsk); | ||||
112 |
bool canceled = Future_GetResult(&tsk.base, res); | ||||
113 |
Task_dtor(&tsk); | ||||
114 |
return canceled; | ||||
115 |
} | ||||
116 |