/home/liu/actions-runner/_work/ccv/ccv/lib/nnc/co.h
Line | Count | Source (jump to first uncovered line) |
1 | | #ifndef GUARD_co_h |
2 | | #define GUARD_co_h |
3 | | |
4 | | #include <stdlib.h> |
5 | | #include <string.h> |
6 | | #include <pthread.h> |
7 | | |
8 | | #include "ccv.h" |
9 | | |
10 | | typedef struct co_routine_s co_routine_t; |
11 | | |
12 | | typedef struct { |
13 | | int active; |
14 | | int stream_await_count; |
15 | | co_routine_t* head; |
16 | | co_routine_t* tail; |
17 | | pthread_t thread; |
18 | | pthread_cond_t notify; |
19 | | pthread_cond_t wait; |
20 | | pthread_mutex_t mutex; |
21 | | } co_scheduler_t; |
22 | | |
23 | | typedef struct { |
24 | | int line; |
25 | | int done; |
26 | | } co_state_t; |
27 | | |
28 | | typedef co_state_t(*co_task_f)(struct co_routine_s* const self, void* const privates); |
29 | | |
30 | | struct co_routine_s { |
31 | | int line; |
32 | | int done; |
33 | | int root; |
34 | | int other_size; |
35 | | co_scheduler_t* scheduler; |
36 | | co_routine_t* prev; |
37 | | co_routine_t* next; |
38 | | co_routine_t* notify_any; |
39 | | co_routine_t* const* others; |
40 | | co_routine_t* callee; |
41 | | co_routine_t* caller; |
42 | | co_task_f fn; |
43 | | }; |
44 | | |
45 | | #define co_params_0(_0,_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,...) _0;_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; |
46 | | |
47 | | #define co_params(...) co_params_0(__VA_ARGS__,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,) |
48 | | |
49 | 106k | #define co_escape(...) __VA_ARGS__ |
50 | | |
51 | | #define co_private(...) __VA_ARGS__ |
52 | | |
53 | | #define co_decl_1(_rettype, _func, _param) \ |
54 | | co_state_t _func(co_routine_t* const _self_, void* const _privates_); \ |
55 | | struct _func ## _param_s { \ |
56 | | _rettype _co_ret; \ |
57 | | struct { \ |
58 | | co_params _param \ |
59 | | } _co_params; \ |
60 | | }; \ |
61 | | size_t _func ## _stack_size(void); |
62 | | |
63 | | #define co_decl_0(_func, _param) \ |
64 | | co_state_t _func(co_routine_t* const _self, void* const _privates_); \ |
65 | | struct _func ## _param_s { \ |
66 | | struct { \ |
67 | | co_params _param \ |
68 | | } _co_params; \ |
69 | | }; \ |
70 | | size_t _func ## _stack_size(void); |
71 | | |
72 | | #define co_decl_sel(_0, _1, _2, ...) _2 |
73 | | |
74 | | #define co_decl(_func_or_rettype, _param_or_func, ...) co_decl_sel(_0, ## __VA_ARGS__, co_decl_1, co_decl_0)(_func_or_rettype, _param_or_func, ## __VA_ARGS__) |
75 | | |
76 | | #define co_task_1(_rettype, _func, _param, _private) \ |
77 | | struct _func ## _private_s { \ |
78 | | struct _func ## _param_s _co_params; \ |
79 | | co_ ## _private \ |
80 | | }; \ |
81 | | size_t _func ## _stack_size(void) { return sizeof(struct _func ## _private_s); } \ |
82 | | co_state_t _func(co_routine_t* const _self_, void* const _privates_) \ |
83 | | { \ |
84 | | struct _private_s { \ |
85 | | struct _func ## _param_s _co_params; \ |
86 | | co_ ## _private \ |
87 | | }; \ |
88 | | switch (_self_->line) { \ |
89 | | case 0: |
90 | | |
91 | | #define co_task_0(_func, _param, _private) \ |
92 | 79.5k | struct _func ## _private_s { \ |
93 | 79.5k | struct _func ## _param_s _co_params; \ |
94 | 79.5k | co_ ## _private \ |
95 | 79.5k | }; \ |
96 | 79.5k | size_t _func ## _stack_size(void) { return sizeof(struct _func ## _private_s); }53.0k \ Unexecuted instantiation: _ccv_nnc_stream_context_add_callback_async_stack_size _ccv_nnc_graph_exec_cases_of_coro_stack_size Line | Count | Source | 96 | 2 | size_t _func ## _stack_size(void) { return sizeof(struct _func ## _private_s); } \ |
_ccv_nnc_graph_wait_any_sub_tasks_stack_size Line | Count | Source | 96 | 2 | size_t _func ## _stack_size(void) { return sizeof(struct _func ## _private_s); } \ |
_ccv_nnc_graph_exec_run_loop_stack_size Line | Count | Source | 96 | 26.5k | size_t _func ## _stack_size(void) { return sizeof(struct _func ## _private_s); } \ |
_ccv_nnc_graph_topsorted_run_coro_stack_size Line | Count | Source | 96 | 26.4k | size_t _func ## _stack_size(void) { return sizeof(struct _func ## _private_s); } \ |
|
97 | 79.5k | co_state_t _func(co_routine_t* const _self_, void* const _privates_) \ |
98 | 79.5k | { \ |
99 | 79.5k | struct _private_s { \ |
100 | 79.5k | struct _func ## _param_s _co_params; \ |
101 | 79.5k | co_ ## _private \ |
102 | 79.5k | }; \ |
103 | 79.5k | switch (_self_->line) { \ |
104 | 53.0k | case 0: |
105 | | |
106 | 53.0k | #define co_task_sel(_0, _1, _2, ...) _2 |
107 | | |
108 | 53.0k | #define co_task(_func_or_rettype, _param_or_func, _private_or_param, ...) co_task_sel(_0, ## __VA_ARGS__, co_task_1, co_task_0)(_func_or_rettype, _param_or_func, _private_or_param, ## __VA_ARGS__) |
109 | | |
110 | | #define co_decl_task_1(_rettype, _func, _param, _private) \ |
111 | | co_decl_1(_rettype, _func, _param) \ |
112 | | co_task_1(_rettype, _func, _param, _private) |
113 | | |
114 | | #define co_decl_task_0(_func, _param, _private) \ |
115 | 26.5k | co_decl_0(_func, _param) \ |
116 | 26.5k | co_task_0(_func, _param, _private) |
117 | | |
118 | 26.5k | #define co_decl_task_sel(_0, _1, _2, ...) _2 |
119 | | |
120 | 26.5k | #define co_decl_task(_func_or_rettype, _param_or_func, _private_or_param, ...) co_decl_task_sel(_0, ## __VA_ARGS__, co_decl_task_1, co_decl_task_0)(_func_or_rettype, _param_or_func, _private_or_param, ## __VA_ARGS__) |
121 | | |
122 | 53.0k | #define co_end() default: return (co_state_t){ __LINE__, 1 }; } } |
123 | | |
124 | 2.86M | #define CO_P(_x) (((struct _private_s*)(_privates_))->_co_params._co_params._x) |
125 | 4.21M | #define CO_V(_x) (((struct _private_s*)(_privates_))->_x) |
126 | | |
127 | 52.9k | #define co_self() (_self_) |
128 | | |
129 | | #define co_yield(_val) do { ((struct _private_s*)(_privates_))->_co_params._co_ret = _val; return (co_state_t){ __LINE__, 0 }; case __LINE__: ; } while (0) |
130 | | |
131 | | #define co_return_1(_val) do { ((struct _private_s*)(_privates_))->_co_params._co_ret = _val; return (co_state_t){ __LINE__, 1 }; } while (0) |
132 | | |
133 | | #define co_return_0() do { return (co_state_t){ __LINE__, 1 }; } while (0) |
134 | | |
135 | | #define co_return_sel(_0, _1, _2, ...) _2 |
136 | | |
137 | | #define co_return(...) co_return_sel(_0, ## __VA_ARGS__, co_return_1, co_return_0)(__VA_ARGS__) |
138 | | |
139 | 53.0k | #define co_init(_task, _func, _param) do { \ |
140 | 53.0k | struct _func ## _param_s params = { \ |
141 | 53.0k | ._co_params = { co_escape _param } \ |
142 | 53.0k | }; \ |
143 | 53.0k | _task->fn = _func; \ |
144 | 53.0k | _task->line = 0; \ |
145 | 53.0k | _task->done = 0; \ |
146 | 53.0k | _task->root = 0; \ |
147 | 53.0k | _task->other_size = 0; \ |
148 | 53.0k | _task->notify_any = 0; \ |
149 | 53.0k | _task->others = 0; \ |
150 | 53.0k | _task->caller = 0; \ |
151 | 53.0k | _task->callee = 0; \ |
152 | 53.0k | if (sizeof(params) > 0) \ |
153 | 53.0k | memcpy(_task + 1, ¶ms, sizeof(params)); \ |
154 | 53.0k | } while (0) |
155 | | |
156 | 53.0k | #define co_size(_func) (sizeof(co_routine_t) + _func ## _stack_size()) |
157 | | |
158 | 53.0k | #define co_new(_func, _param) ({ \ |
159 | 53.0k | co_routine_t* const task = ccmalloc(co_size(_func)); \ |
160 | 53.0k | co_init(task, _func, _param); \ |
161 | 53.0k | task; \ |
162 | 53.0k | }) |
163 | | |
164 | | #define co_retval_2(_task, _rettype) *(_rettype*)(_task + 1) |
165 | | |
166 | | #define co_retval_0() ((struct _private_s*)(_privates_))->_co_params._co_ret |
167 | | |
168 | | #define co_retval_sel(_0, _1, _2, _3, ...) _3 |
169 | | |
170 | | #define co_retval(...) co_retval_sel(_0, ## __VA_ARGS__, co_retval_2, co_retval_1, co_retval_0)(__VA_ARGS__) |
171 | | |
172 | 2 | #define co_await_any(_tasks, _task_size) do { if (!_co_await_any(_self_, _tasks, _task_size)) { return (co_state_t){ __LINE__, 0 }; } case __LINE__: ; } while (0) |
173 | | |
174 | | #define co_await_1(_task, _val) do { \ |
175 | | co_await_any(&(_task), 1); \ |
176 | | _val = co_retval(_task, typeof(_val)); \ |
177 | | } while (0) |
178 | | |
179 | | #define co_await_0(_task) \ |
180 | 0 | co_await_any(&(_task), 1) |
181 | | |
182 | 0 | #define co_await_sel(_0, _1, _2, ...) _2 |
183 | | |
184 | 0 | #define co_await(_task, ...) co_await_sel(_0, ## __VA_ARGS__, co_await_1, co_await_0)(_task, ## __VA_ARGS__) |
185 | | |
186 | | #define co_apply_1(_func, _param, _val) do { \ |
187 | | _self_->callee = co_new(_func, _param); \ |
188 | | _co_apply(_self_, _self_->callee); \ |
189 | | return (co_state_t){ __LINE__, 0 }; \ |
190 | | case __LINE__: \ |
191 | | _val = co_retval(&(_self_->callee), typeof(_val)); \ |
192 | | co_free(_self_->callee); \ |
193 | | _self_->callee = 0; \ |
194 | | } while (0) |
195 | | |
196 | 26.5k | #define co_apply_0(_func, _param) do { \ |
197 | 26.5k | _self_->callee = co_new(_func, _param); \ |
198 | 26.5k | _co_apply(_self_, _self_->callee); \ |
199 | 26.5k | return (co_state_t){ __LINE__, 0 }; \ |
200 | 26.5k | case __LINE__: \ |
201 | 26.5k | co_free(_self_->callee); \ |
202 | 26.5k | _self_->callee = 0; \ |
203 | 26.5k | } while (0) |
204 | | |
205 | 26.5k | #define co_apply_sel(_0, _1, _2, ...) _2 |
206 | | |
207 | 26.5k | #define co_apply(_func, _param, ...) co_apply_sel(_0, ## __VA_ARGS__, co_apply_1, co_apply_0)(_func, _param, ## __VA_ARGS__) |
208 | | |
209 | | #define co_resume_1(_task, _val) do { \ |
210 | | _co_resume(_self_, _task); \ |
211 | | return (co_state_t){ __LINE__, 0 }; \ |
212 | | case __LINE__: \ |
213 | | _self_->callee = 0; \ |
214 | | _val = co_retval(_task, typeof(_val)); \ |
215 | | } while (0) |
216 | | |
217 | 4 | #define co_resume_0(_task) do { \ |
218 | 4 | _co_resume(_self_, _task); \ |
219 | 4 | return (co_state_t){ __LINE__, 0 }; \ |
220 | 4 | case __LINE__: \ |
221 | 4 | _self_->callee = 0; \ |
222 | 4 | } while (0) |
223 | | |
224 | 4 | #define co_resume_sel(_0, _1, _2, ...) _2 |
225 | | |
226 | 4 | #define co_resume(_task, ...) co_resume_sel(_0, ## __VA_ARGS__, co_resume_1, co_resume_0)(_task, ## __VA_ARGS__) |
227 | | |
228 | | void _co_prepend_task(co_scheduler_t* const scheduler, co_routine_t* const task); |
229 | | void _co_apply(co_routine_t* const self, co_routine_t* const task); |
230 | | void _co_resume(co_routine_t* const self, co_routine_t* const task); |
231 | | int _co_await_any(co_routine_t* const self, co_routine_t* const* const tasks, const int task_size); |
232 | | |
233 | | void co_free(co_routine_t* const task); |
234 | | int co_is_done(const co_routine_t* const task); |
235 | | co_scheduler_t* co_scheduler_new(void); |
236 | | void co_scheduler_free(co_scheduler_t* const scheduler); |
237 | | void co_schedule(co_scheduler_t* const scheduler, co_routine_t* const task); |
238 | | int co_is_on_scheduler(co_scheduler_t* const scheduler); |
239 | | int co_scheduler_is_active(co_scheduler_t* const scheduler); |
240 | | |
241 | | #endif |