Line | Branch | Exec | Source |
---|---|---|---|
1 | #include <unistd.h> | ||
2 | #include "gwion_util.h" | ||
3 | #include "gwion_ast.h" | ||
4 | #include "gwion_env.h" | ||
5 | #include "gwion_thread.h" | ||
6 | #include "vm.h" | ||
7 | #include "instr.h" | ||
8 | #include "shreduler_private.h" | ||
9 | #include "gwion.h" | ||
10 | #include "object.h" | ||
11 | #include "operator.h" | ||
12 | #include "import.h" | ||
13 | #include "emit.h" | ||
14 | #include "specialid.h" | ||
15 | #include "gwi.h" | ||
16 | #include "ugen.h" | ||
17 | |||
18 | static m_int o_fork_thread, o_shred_cancel, | ||
19 | o_fork_done, o_fork_ev; | ||
20 | |||
21 | #define FORK_THREAD(o) *(THREAD_TYPE *)(o->data + o_fork_thread) | ||
22 | |||
23 | 79 | VM_Shred new_shred_base(const VM_Shred shred, const VM_Code code) { | |
24 | 79 | const VM_Shred sh = new_vm_shred(shred->info->mp, code); | |
25 | 79 | vmcode_addref(code); | |
26 | 79 | sh->base = shred->base; | |
27 | 79 | return sh; | |
28 | } | ||
29 | |||
30 | 1062 | M_Object new_shred(const VM_Shred shred) { | |
31 | const M_Object obj = | ||
32 | 1062 | new_object(shred->info->mp, shred->info->vm->gwion->type[et_shred]); | |
33 | 1062 | ME(obj) = shred; | |
34 | 1062 | return obj; | |
35 | } | ||
36 | |||
37 | 5 | ANN static inline M_Object fork_object(const VM_Shred shred, const Type t) { | |
38 | 5 | const Gwion gwion = shred->info->vm->gwion; | |
39 | 5 | const M_Object o = new_object(gwion->mp, t); | |
40 | 10 | *(M_Object *)(o->data + o_fork_ev) = | |
41 | 5 | new_object(gwion->mp, gwion->type[et_event]); | |
42 | 5 | vector_init(&EV_SHREDS(*(M_Object *)(o->data + o_fork_ev))); | |
43 | 5 | return o; | |
44 | } | ||
45 | |||
46 | 5 | ANN M_Object new_fork(const VM_Shred shred, const VM_Code code, const Type t) { | |
47 | 5 | VM * parent = shred->info->vm; | |
48 | 5 | const VM_Shred sh = new_shred_base(shred, code); | |
49 | 5 | VM * vm = (sh->info->vm = gwion_cpy(parent)); | |
50 | 5 | vm->parent = parent; | |
51 | 5 | const M_Object o = sh->info->me = fork_object(shred, t); | |
52 | 5 | ME(o) = sh; | |
53 | 5 | shreduler_add(vm->shreduler, sh); | |
54 | 5 | return o; | |
55 | } | ||
56 | |||
57 | 2 | static MFUN(gw_shred_exit) { | |
58 | 2 | const VM_Shred s = ME(o); | |
59 |
1/2✓ Branch 0 taken 2 times.
✗ Branch 1 not taken.
|
2 | if((m_int)s->tick->prev != -1) |
60 | 2 | shreduler_remove(s->tick->shreduler, s, true); | |
61 | 2 | } | |
62 | |||
63 | 5 | static MFUN(vm_shred_id) { | |
64 | 5 | const VM_Shred s = ME(o); | |
65 | 5 | *(m_int *)RETURN = s->tick->xid; | |
66 | 5 | } | |
67 | |||
68 | 1 | static MFUN(vm_shred_is_running) { | |
69 | 1 | const VM_Shred s = ME(o); | |
70 |
3/6✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1 times.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✓ Branch 5 taken 1 times.
|
1 | *(m_uint *)RETURN = ((m_int)s->tick->prev != -1 && (s->tick->prev || s->tick->next)) ? true : false; |
71 | 1 | } | |
72 | |||
73 | 1 | static MFUN(vm_shred_is_done) { | |
74 | 1 | *(m_uint *)RETURN = (m_int)ME(o)->tick->prev == -1; | |
75 | 1 | } | |
76 | |||
77 | 22 | static MFUN(shred_yield) { | |
78 | 22 | const VM_Shred s = ME(o); | |
79 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
|
22 | if((m_int)s->tick->prev == -1) return; |
80 | 22 | const Shreduler sh = s->tick->shreduler; | |
81 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 22 times.
|
22 | if (s != shred) shreduler_remove(sh, s, false); |
82 | 22 | shredule(sh, s, GWION_EPSILON); | |
83 | } | ||
84 | |||
85 | 1 | static SFUN(vm_shred_from_id) { | |
86 | 1 | const m_int index = *(m_int *)MEM(0); | |
87 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (index > 0) { |
88 | ✗ | const Vector v = &shred->tick->shreduler->active_shreds; | |
89 | ✗ | for (m_uint i = 0; i < vector_size(v); ++i) { | |
90 | ✗ | const VM_Shred s = | |
91 | ✗ | (VM_Shred)vector_at(v, i); | |
92 | ✗ | if (s->tick->xid == (m_uint)index) { | |
93 | ✗ | *(M_Object *)RETURN = s->info->me; | |
94 | ✗ | return; | |
95 | } | ||
96 | } | ||
97 | } | ||
98 | 1 | xfun_handle(shred, "InvalidShredRequest"); | |
99 | } | ||
100 | |||
101 | ✗ | static MFUN(shred_args) { | |
102 | ✗ | const VM_Shred s = ME(o); | |
103 | ✗ | *(m_uint *)RETURN = s->info->args.ptr ? vector_size(&s->info->args) : 0; | |
104 | } | ||
105 | |||
106 | ✗ | static MFUN(shred_arg) { | |
107 | ✗ | const VM_Shred s = ME(o); | |
108 | ✗ | const m_int idx = *(m_int *)MEM(SZ_INT); | |
109 | ✗ | if (s->info->args.ptr && idx >= 0 && (m_uint)idx < vector_size(&s->info->args)) { | |
110 | ✗ | const m_str str = (m_str)vector_at(&s->info->args, *(m_uint *)MEM(SZ_INT)); | |
111 | ✗ | *(M_Object *)RETURN = new_string(shred->info->vm->gwion, str); | |
112 | ✗ | } else xfun_handle(shred, "InvalidShredArgumentRequest"); | |
113 | } | ||
114 | |||
115 | #ifndef BUILD_ON_WINDOWS | ||
116 | #define PATH_CHR '/' | ||
117 | #else | ||
118 | #define PATH_CHR '\\' | ||
119 | #endif | ||
120 | |||
121 | #define describe_name(name, src) \ | ||
122 | static MFUN(shred##name##_name) { \ | ||
123 | const VM_Shred s = ME(o); \ | ||
124 | const m_str str = code_name((src), 0); \ | ||
125 | *(m_uint *)RETURN = (m_uint)new_string(shred->info->vm->gwion, str); \ | ||
126 | } | ||
127 | ✗ | describe_name(, s->info->orig->name) describe_name(_code, s->code->name) | |
128 | |||
129 | #define describe_path_and_dir(name, src) \ | ||
130 | static MFUN(shred##name##_path) { \ | ||
131 | const VM_Shred s = ME(o); \ | ||
132 | const m_str str = code_name((src), 1); \ | ||
133 | *(m_uint *)RETURN = (m_uint)new_string(shred->info->vm->gwion, str); \ | ||
134 | } \ | ||
135 | static MFUN(shred##name##_dir) { \ | ||
136 | const VM_Shred s = ME(o); \ | ||
137 | const m_str str = code_name((src), 1); \ | ||
138 | const size_t len = strlen(str); \ | ||
139 | char c[len + 1]; \ | ||
140 | strcpy(c, str); \ | ||
141 | size_t sz = len; \ | ||
142 | while (sz) { \ | ||
143 | if (c[sz] == PATH_CHR) { \ | ||
144 | c[sz] = 0; \ | ||
145 | break; \ | ||
146 | } \ | ||
147 | --sz; \ | ||
148 | } \ | ||
149 | *(m_uint *)RETURN = (m_uint)new_string(shred->info->vm->gwion, c); \ | ||
150 | } | ||
151 | ✗ | describe_path_and_dir(, s->info->orig->name) | |
152 | ✗ | describe_path_and_dir(_code, s->code->name) | |
153 | |||
154 | 425 | static DTOR(shred_dtor) { | |
155 | 425 | VM_Shred s = ME(o); | |
156 | 425 | free_vm_shred(s); | |
157 | 425 | } | |
158 | |||
159 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | static MFUN(shred_lock) { if(ME(o)->tick) MUTEX_LOCK(ME(o)->mutex); } |
160 | |||
161 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | static MFUN(shred_unlock) { if(ME(o)->tick) MUTEX_UNLOCK(ME(o)->mutex); } |
162 | |||
163 | 6 | static void stop(const M_Object o) { | |
164 | 6 | VM *vm = ME(o)->info->vm; | |
165 | 6 | MUTEX_LOCK(vm->shreduler->mutex); | |
166 | 6 | MUTEX_LOCK(ME(o)->mutex); | |
167 | 6 | vm->shreduler->bbq->is_running = 0; | |
168 | 6 | *(m_int *)(o->data + o_shred_cancel) = 1; | |
169 | 6 | MUTEX_UNLOCK(ME(o)->mutex); | |
170 | 6 | MUTEX_UNLOCK(vm->shreduler->mutex); | |
171 | 6 | } | |
172 | |||
173 | 6 | static inline void join(const M_Object o) { | |
174 |
2/2✓ Branch 0 taken 5 times.
✓ Branch 1 taken 1 times.
|
6 | if (FORK_THREAD(o)) { |
175 | 5 | THREAD_JOIN(FORK_THREAD(o)); | |
176 | 5 | FORK_THREAD(o) = 0; | |
177 | } | ||
178 | 6 | } | |
179 | |||
180 | 1 | static DTOR(fork_dtor) { | |
181 | 1 | VM *parent = ME(o)->info->vm->parent; | |
182 | // MUTEX_LOCK(parent->shreduler->mutex); | ||
183 | 1 | MUTEX_LOCK(ME(o)->mutex); | |
184 | 1 | *(m_int *)(o->data + o_fork_done) = 1; | |
185 | 1 | MUTEX_UNLOCK(ME(o)->mutex); | |
186 | 1 | stop(o); | |
187 | 1 | join(o); | |
188 | // MUTEX_UNLOCK(parent->shreduler->mutex); | ||
189 | 1 | MUTEX_LOCK(parent->shreduler->mutex); | |
190 | // MUTEX_LOCK(ME(o)->mutex); | ||
191 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (parent->gwion->data->child.ptr) { |
192 | 1 | const m_int idx = vector_find(&parent->gwion->data->child, (vtype)o); | |
193 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (idx > -1) VPTR(&parent->gwion->data->child, idx) = 0; |
194 | } | ||
195 |
1/2✓ Branch 0 taken 1 times.
✗ Branch 1 not taken.
|
1 | if (!parent->gwion->data->child2.ptr) |
196 | 1 | vector_init(&parent->gwion->data->child2); | |
197 | 1 | vector_add(&parent->gwion->data->child2, (vtype)ME(o)->info->vm->gwion); | |
198 | // MUTEX_UNLOCK(ME(o)->mutex); | ||
199 | 1 | MUTEX_UNLOCK(parent->shreduler->mutex); | |
200 | 1 | vmcode_remref(ME(o)->code, ME(o)->info->vm->gwion); | |
201 | 1 | } | |
202 | |||
203 | 1 | static MFUN(fork_join) { | |
204 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (*(m_int *)(o->data + o_fork_done)) return; |
205 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | if (!ME(o)->tick) return; |
206 | 1 | shred->info->me->ref++; | |
207 | 1 | vector_add(&EV_SHREDS(*(M_Object *)(o->data + o_fork_ev)), (vtype)shred); | |
208 | 1 | shreduler_remove(shred->tick->shreduler, shred, false); | |
209 | } | ||
210 | |||
211 | 2 | static MFUN(shred_cancel) { | |
212 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 2 times.
|
2 | if(!ME(o)->tick)return; |
213 | // vm_lock(ME(o)->info->vm); | ||
214 | 2 | MUTEX_LOCK(ME(o)->mutex); | |
215 | 2 | *(m_int *)(o->data + o_shred_cancel) = *(m_int *)MEM(SZ_INT); | |
216 | 2 | MUTEX_UNLOCK(ME(o)->mutex); | |
217 | // vm_unlock(ME(o)->info->vm); | ||
218 | } | ||
219 | |||
220 | 2 | static MFUN(shred_test_cancel) { | |
221 | 2 | MUTEX_LOCK(ME(o)->mutex); | |
222 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 1 times.
|
2 | if (*(m_int *)(o->data + o_shred_cancel)) { |
223 | 1 | MUTEX_UNLOCK(ME(o)->mutex); | |
224 | 1 | vm_shred_exit(ME(o)); | |
225 | } else | ||
226 | 1 | MUTEX_UNLOCK(ME(o)->mutex); | |
227 | 2 | } | |
228 | |||
229 | ✗ | static MFUN(fork_test_cancel) { | |
230 | ✗ | VM *parent = ME(o)->info->vm; | |
231 | ✗ | MUTEX_LOCK(parent->shreduler->mutex); | |
232 | ✗ | if (*(m_int *)(o->data + o_shred_cancel)) { | |
233 | ✗ | MUTEX_UNLOCK(parent->shreduler->mutex); | |
234 | ✗ | stop(o); | |
235 | ✗ | join(o); | |
236 | ✗ | _release(o, ME(o)); | |
237 | ✗ | vm_shred_exit(ME(o)); | |
238 | } else | ||
239 | ✗ | MUTEX_UNLOCK(parent->shreduler->mutex); | |
240 | } | ||
241 | |||
242 | ✗ | static MFUN(shred_now) { | |
243 | ✗ | VM *vm = ME(o)->info->vm; | |
244 | ✗ | while (vm->parent) vm = vm->parent; | |
245 | ✗ | MUTEX_LOCK(vm->shreduler->mutex); | |
246 | ✗ | *(m_float *)RETURN = vm->bbq->pos; | |
247 | ✗ | MUTEX_UNLOCK(vm->shreduler->mutex); | |
248 | } | ||
249 | |||
250 | ✗ | static MFUN(shred_blackhole) { | |
251 | ✗ | VM *vm = ME(o)->info->vm; | |
252 | ✗ | const UGen u = (UGen)vector_front(&vm->ugen); | |
253 | ✗ | M_Object blackhole = u->module.gen.data; | |
254 | // adding ref for the moment | ||
255 | ✗ | blackhole->ref++; | |
256 | ✗ | *(void**)RETURN = u->module.gen.data; | |
257 | } | ||
258 | |||
259 | struct ThreadLauncher { | ||
260 | MUTEX_TYPE mutex; | ||
261 | THREAD_COND_TYPE cond; | ||
262 | VM * vm; | ||
263 | }; | ||
264 | |||
265 | 2880007 | static inline int fork_running(VM *vm, const M_Object o) { | |
266 | 2880007 | MUTEX_LOCK(ME(o)->mutex); | |
267 | 2880007 | const int cancel = *(m_int *)(o->data + o_shred_cancel); | |
268 | 2880007 | MUTEX_UNLOCK(ME(o)->mutex); | |
269 |
2/2✓ Branch 0 taken 4 times.
✓ Branch 1 taken 2880003 times.
|
2880007 | if(cancel)return false; |
270 | 2880003 | MUTEX_LOCK(vm->shreduler->mutex); | |
271 | 2880003 | const int ret = vm->bbq->is_running; | |
272 | 2880003 | MUTEX_UNLOCK(vm->shreduler->mutex); | |
273 | 2880003 | return ret; | |
274 | } | ||
275 | |||
276 | 5 | static ANN THREAD_FUNC(fork_run) { | |
277 | 5 | struct ThreadLauncher *tl = data; | |
278 | 5 | VM * vm = tl->vm; | |
279 | 5 | MUTEX_TYPE mutex = tl->mutex; | |
280 | 5 | const M_Object me = vm->shreduler->list->self->info->me; | |
281 | 5 | MUTEX_COND_LOCK(mutex); | |
282 | 5 | THREAD_COND_SIGNAL(tl->cond); | |
283 | 5 | MUTEX_COND_UNLOCK(mutex); | |
284 | // THREAD_COND_CLEANUP(tl->cond); | ||
285 | // MUTEX_CLEANUP(tl->mutex); | ||
286 |
2/2✓ Branch 1 taken 2880002 times.
✓ Branch 2 taken 5 times.
|
2880007 | while (fork_running(vm, me)) { |
287 | 2880002 | vm_run_audio(vm); | |
288 | 2880002 | ++vm->bbq->pos; | |
289 | } | ||
290 | 5 | gwion_end_child(ME(me), vm->gwion); | |
291 | 5 | vm_lock(vm); | |
292 | // MUTEX_LOCK(vm->shreduler->mutex); | ||
293 | // MUTEX_LOCK(vm->parent->shreduler->mutex); | ||
294 | 5 | MUTEX_LOCK(ME(me)->mutex); | |
295 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
|
5 | if (!*(m_int *)(me->data + o_shred_cancel) && |
296 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1 times.
|
1 | me->type_ref != vm->gwion->type[et_fork]) |
297 | ✗ | memcpy(me->data + vm->gwion->type[et_fork]->nspc->offset, ME(me)->reg, | |
298 | ✗ | ((Type)vector_front(&me->type_ref->info->tuple->types))->size); | |
299 | 5 | *(m_int *)(me->data + o_fork_done) = 1; | |
300 | 5 | MUTEX_UNLOCK(ME(me)->mutex); | |
301 |
2/2✓ Branch 0 taken 1 times.
✓ Branch 1 taken 4 times.
|
5 | if (!*(m_int *)(me->data + o_shred_cancel)) |
302 | 1 | broadcast(*(M_Object *)(me->data + o_fork_ev)); | |
303 | 5 | vm_unlock(vm); | |
304 | // MUTEX_UNLOCK(vm->parent->shreduler->mutex); | ||
305 | // MUTEX_UNLOCK(vm->shreduler->mutex); | ||
306 | 5 | THREAD_RETURN(0); | |
307 | } | ||
308 | |||
309 | 5 | ANN void fork_launch(const M_Object o) { | |
310 | MUTEX_TYPE mutex; | ||
311 | 5 | MUTEX_SETUP(mutex); | |
312 | THREAD_COND_TYPE cond; | ||
313 | 5 | THREAD_COND_SETUP(cond); | |
314 | 5 | struct ThreadLauncher tl = { | |
315 | 5 | .mutex = mutex, .cond = cond, .vm = ME(o)->info->vm}; | |
316 | 5 | ++o->ref; | |
317 | 5 | MUTEX_COND_LOCK(mutex); | |
318 | 5 | THREAD_CREATE(FORK_THREAD(o), fork_run, &tl); | |
319 | 5 | THREAD_COND_WAIT(cond, mutex); | |
320 | 5 | MUTEX_COND_UNLOCK(mutex); | |
321 | 5 | THREAD_COND_CLEANUP(cond); | |
322 | 5 | MUTEX_CLEANUP(mutex); | |
323 | 5 | } | |
324 | |||
325 | 5 | ANN void fork_clean(const VM_Shred shred, const Vector v) { | |
326 |
2/2✓ Branch 1 taken 5 times.
✓ Branch 2 taken 5 times.
|
10 | for (m_uint i = 0; i < vector_size(v); ++i) { |
327 | 5 | const M_Object o = (M_Object)vector_at(v, i); | |
328 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if (!o) continue; |
329 | 5 | stop(o); | |
330 | } | ||
331 |
2/2✓ Branch 1 taken 5 times.
✓ Branch 2 taken 5 times.
|
10 | for (m_uint i = 0; i < vector_size(v); ++i) { |
332 | 5 | const M_Object o = (M_Object)vector_at(v, i); | |
333 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if (!o) continue; |
334 | 5 | join(o); | |
335 | } | ||
336 |
2/2✓ Branch 1 taken 5 times.
✓ Branch 2 taken 5 times.
|
10 | for (m_uint i = 0; i < vector_size(v); ++i) { |
337 | 5 | const M_Object o = (M_Object)vector_at(v, i); | |
338 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 5 times.
|
5 | if (!o) continue; |
339 | 5 | _release(o, shred); | |
340 | } | ||
341 | 5 | vector_release(v); | |
342 | 5 | v->ptr = NULL; | |
343 | 5 | } | |
344 | |||
345 | 638 | GWION_IMPORT(shred) { | |
346 | 638 | const Type t_shred = gwi_class_ini(gwi, "Shred", NULL); | |
347 | 638 | gwi_class_xtor(gwi, NULL, shred_dtor); | |
348 | |||
349 | 638 | t_shred->nspc->offset += SZ_INT; | |
350 | |||
351 | 638 | gwi_item_ini(gwi, "int", "cancel"); | |
352 | 638 | GWI_BB((o_shred_cancel = gwi_item_end(gwi, ae_flag_const, num, 0))) | |
353 | |||
354 | 638 | gwi_func_ini(gwi, "void", "exit"); | |
355 | 638 | GWI_BB(gwi_func_end(gwi, gw_shred_exit, ae_flag_none)) | |
356 | |||
357 | 638 | gwi_func_ini(gwi, "bool", "running"); | |
358 | 638 | GWI_BB(gwi_func_end(gwi, vm_shred_is_running, ae_flag_none)) | |
359 | |||
360 | 638 | gwi_func_ini(gwi, "bool", "done"); | |
361 | 638 | GWI_BB(gwi_func_end(gwi, vm_shred_is_done, ae_flag_none)) | |
362 | |||
363 | 638 | gwi_func_ini(gwi, "int", "id"); | |
364 | 638 | GWI_BB(gwi_func_end(gwi, vm_shred_id, ae_flag_none)) | |
365 | |||
366 | 638 | gwi_func_ini(gwi, "Shred", "fromId"); | |
367 | 638 | gwi_func_arg(gwi, "int", "xid"); | |
368 | 638 | GWI_BB(gwi_func_end(gwi, vm_shred_from_id, ae_flag_static)) | |
369 | |||
370 | 638 | gwi_func_ini(gwi, "void", "yield"); | |
371 | 638 | GWI_BB(gwi_func_end(gwi, shred_yield, ae_flag_none)) | |
372 | |||
373 | 638 | gwi_func_ini(gwi, "int", "args"); | |
374 | 638 | GWI_BB(gwi_func_end(gwi, shred_args, ae_flag_none)) | |
375 | |||
376 | 638 | gwi_func_ini(gwi, "string", "arg"); | |
377 | 638 | gwi_func_arg(gwi, "int", "n"); | |
378 | 638 | GWI_BB(gwi_func_end(gwi, shred_arg, ae_flag_none)) | |
379 | |||
380 | 638 | gwi_func_ini(gwi, "string", "name"); | |
381 | 638 | GWI_BB(gwi_func_end(gwi, shred_name, ae_flag_none)) | |
382 | |||
383 | 638 | gwi_func_ini(gwi, "string", "path"); | |
384 | 638 | GWI_BB(gwi_func_end(gwi, shred_path, ae_flag_none)) | |
385 | |||
386 | 638 | gwi_func_ini(gwi, "string", "dir"); | |
387 | 638 | GWI_BB(gwi_func_end(gwi, shred_dir, ae_flag_none)) | |
388 | |||
389 | 638 | gwi_func_ini(gwi, "string", "code_name"); | |
390 | 638 | GWI_BB(gwi_func_end(gwi, shred_code_name, ae_flag_none)) | |
391 | |||
392 | 638 | gwi_func_ini(gwi, "string", "code_path"); | |
393 | 638 | GWI_BB(gwi_func_end(gwi, shred_code_path, ae_flag_none)) | |
394 | |||
395 | 638 | gwi_func_ini(gwi, "string", "code_dir"); | |
396 | 638 | GWI_BB(gwi_func_end(gwi, shred_code_dir, ae_flag_none)) | |
397 | |||
398 | 638 | gwi_func_ini(gwi, "void", "set_cancel"); | |
399 | 638 | gwi_func_arg(gwi, "int", "n"); | |
400 | 638 | GWI_BB(gwi_func_end(gwi, shred_cancel, ae_flag_none)) | |
401 | 638 | gwi_func_ini(gwi, "void", "test_cancel"); | |
402 | 638 | GWI_BB(gwi_func_end(gwi, shred_test_cancel, ae_flag_none)) | |
403 | 638 | gwi_func_ini(gwi, "void", "lock"); | |
404 | 638 | GWI_BB(gwi_func_end(gwi, shred_lock, ae_flag_none)) | |
405 | 638 | gwi_func_ini(gwi, "void", "unlock"); | |
406 | 638 | GWI_BB(gwi_func_end(gwi, shred_unlock, ae_flag_none)) | |
407 | 638 | gwi_func_ini(gwi, "float", "get_now"); | |
408 | 638 | GWI_BB(gwi_func_end(gwi, shred_now, ae_flag_none)) | |
409 | |||
410 | 638 | gwi_func_ini(gwi, "UGen", "get_blackhole"); | |
411 | 638 | GWI_BB(gwi_func_end(gwi, shred_blackhole, ae_flag_none)) | |
412 | |||
413 | |||
414 | 638 | GWI_BB(gwi_class_end(gwi)) | |
415 | 638 | SET_FLAG(t_shred, abstract | ae_flag_final); | |
416 | 638 | gwi->gwion->type[et_shred] = t_shred; | |
417 | |||
418 | 638 | struct SpecialId_ spid = {.type = t_shred, .exec = RegPushMe, .is_const = 1}; | |
419 | 638 | gwi_specialid(gwi, "me", &spid); | |
420 | |||
421 | 638 | const Type t_fork = gwi_class_ini(gwi, "Fork", "Shred"); | |
422 | 638 | gwi_class_xtor(gwi, NULL, fork_dtor); | |
423 | 638 | gwi->gwion->type[et_fork] = t_fork; | |
424 | 638 | o_fork_thread = t_fork->nspc->offset; | |
425 | 638 | t_fork->nspc->offset += SZ_INT; | |
426 | |||
427 | 638 | gwi_item_ini(gwi, "int", "is_done"); | |
428 | 638 | GWI_BB((o_fork_done = gwi_item_end(gwi, ae_flag_const, num, 0))) | |
429 | 638 | gwi_item_ini(gwi, "Event", "ev"); | |
430 | 638 | GWI_BB((o_fork_ev = gwi_item_end(gwi, ae_flag_const, num, 0))) | |
431 | 638 | gwi_func_ini(gwi, "void", "join"); | |
432 | 638 | GWI_BB(gwi_func_end(gwi, fork_join, ae_flag_none)) | |
433 | 638 | gwi_func_ini(gwi, "void", "test_cancel"); | |
434 | 638 | GWI_BB(gwi_func_end(gwi, fork_test_cancel, ae_flag_none)) | |
435 | 638 | GWI_BB(gwi_class_end(gwi)) | |
436 | 638 | SET_FLAG(t_fork, abstract | ae_flag_final); | |
437 | |||
438 | 638 | const Type t_typed = gwi_class_ini(gwi, "TypedFork:[A]", "Fork"); | |
439 | 638 | gwi_item_ini(gwi, "A", "retval"); | |
440 | 638 | GWI_BB(gwi_item_end(gwi, ae_flag_const, num, 0)) | |
441 | 638 | GWI_BB(gwi_class_end(gwi)) | |
442 | 638 | SET_FLAG(t_typed, abstract | ae_flag_final); | |
443 | 638 | return GW_OK; | |
444 | } | ||
445 |