137 lines2.7 KB
Newer
Older
-
+
commited
{line.log.rev}
on
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,
5 months ago
49
size_t stack_size,
8 months ago
37
50
Task_Entry entry,
51
void *param
52
){
53
assert(Coroutine_IsStarted());
54
Future_ctor(&tsk->base);
55
tsk->base.vfptrs = &Task_vfptrs;
56
tsk->entry = entry;
57
tsk->param = param;
5 months ago
58
tsk->cor = Coroutine_New(stack_size, Task_entry);
8 months ago
37
59
tsk->awaiting_future = NULL;
60
tsk->canceled = false;
61
tsk->cancel_value = NULL;
62
if (current_task){
63
Coroutine_Continue(tsk->cor, tsk, false);
64
}
65
}
66
67
68
void Task_dtor(
69
Task *tsk
70
){
71
Coroutine_Delete(tsk->cor);
72
Future_dtor(&tsk->base);
73
}
74
75
76
Task *Task_New(
5 months ago
77
size_t stack_size,
8 months ago
37
78
Task_Entry entry,
79
void *param
80
){
81
Task *tsk = malloc(sizeof(Task));
5 months ago
82
Task_ctor(tsk, stack_size, entry, param);
8 months ago
37
83
return tsk;
84
}
85
86
87
void Task_Delete(
88
Task *tsk
89
){
90
Future_Delete(&tsk->base);
91
}
92
93
94
void Task_Cancel(
95
Task *tsk,
96
void *cancel_value
97
){
98
if (!tsk->canceled){
99
tsk->canceled = true;
100
tsk->cancel_value = cancel_value;
101
Future *awaiting_future = tsk->awaiting_future;
102
if (awaiting_future){
103
Future_SetResult(awaiting_future, true, NULL);
104
}
105
}
106
}
107
108
3 months ago
109
struct Task_Run_Params {
110
size_t stack_size;
111
Task_Entry start;
112
void *value;
113
void **res;
114
};
115
116
static Coroutine_Err Task_Runner(void *_params)
117
{
118
struct Task_Run_Params *params = (struct Task_Run_Params *)_params;
119
8 months ago
37
120
Task tsk;
3 months ago
121
Task_ctor(&tsk, params->stack_size, params->start, params->value);
122
Coroutine_Err err = Coroutine_Run_Coroutine(tsk.cor, &tsk);
123
if (!err){
124
err = Future_GetResult(&tsk.base, params->res);
125
}
8 months ago
37
126
Task_dtor(&tsk);
3 months ago
127
return err;
8 months ago
37
128
}
3 months ago
129
130
bool Task_Run(size_t stack_size, Task_Entry start, void *value, void **res){
131
if (current_task){
132
return Coroutine_Err_SystemRunning;
133
}
134
struct Task_Run_Params params = {stack_size, start, value, res};
135
return Coroutine_RunSystem(Task_Runner, &params);
136
}
137