| 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 |