1 |
|
|
#include <stdlib.h> |
2 |
|
|
#include "gwion_util.h" |
3 |
|
|
#include "gwion_ast.h" |
4 |
|
|
#include "gwion_env.h" |
5 |
|
|
#include "vm.h" |
6 |
|
|
#include "object.h" |
7 |
|
|
#include "driver.h" |
8 |
|
|
#include "shreduler_private.h" |
9 |
|
|
|
10 |
|
713 |
ANN void shreduler_set_loop(const Shreduler s, const m_bool loop) { |
11 |
|
713 |
s->loop = loop > 0; |
12 |
|
713 |
} |
13 |
|
|
|
14 |
|
5836647 |
ANN VM_Shred shreduler_get(const Shreduler s) { |
15 |
|
5836647 |
Driver *const bbq = s->bbq; |
16 |
|
5836647 |
struct ShredTick_ *const tk = s->list; |
17 |
✓✓ |
5836647 |
if(!tk) { |
18 |
✓✓✓✓
|
1947947 |
if(!vector_size(&s->shreds) && !s->loop) |
19 |
|
717 |
bbq->is_running = 0; |
20 |
|
1947947 |
return NULL; |
21 |
|
|
} |
22 |
|
3888700 |
const m_float time = (m_float)bbq->pos + (m_float)GWION_EPSILON; |
23 |
✓✓ |
3888700 |
if(tk->wake_time <= time) { |
24 |
✓✓ |
644 |
if((s->list = tk->next)) |
25 |
|
160 |
s->list->prev = NULL; |
26 |
|
644 |
tk->next = tk->prev = NULL; |
27 |
|
644 |
s->curr = tk; |
28 |
|
644 |
return tk->self; |
29 |
|
|
} |
30 |
|
3888056 |
return NULL; |
31 |
|
|
} |
32 |
|
|
|
33 |
|
75 |
ANN static void shreduler_parent(const VM_Shred out, const Vector v) { |
34 |
|
75 |
vector_rem2(v, (vtype)out); |
35 |
✓✓ |
75 |
if(!vector_size(v)) { |
36 |
|
32 |
vector_release(v); |
37 |
|
32 |
out->tick->parent->child.ptr = NULL; |
38 |
|
|
} |
39 |
|
75 |
} |
40 |
|
|
|
41 |
|
10 |
ANN static inline void shreduler_child(const Vector v) { |
42 |
✓✓ |
43 |
for(m_uint i = vector_size(v) + 1; --i;) { |
43 |
|
23 |
const VM_Shred child = (VM_Shred)vector_at(v, i - 1); |
44 |
|
23 |
shreduler_remove(child->info->vm->shreduler, child, 1); |
45 |
|
|
} |
46 |
|
10 |
} |
47 |
|
|
|
48 |
|
501 |
ANN static void shreduler_erase(const Shreduler s, struct ShredTick_ *tk) { |
49 |
✓✓ |
501 |
if(tk->parent) |
50 |
|
75 |
shreduler_parent(tk->self, &tk->parent->child); |
51 |
✓✓ |
501 |
if(tk->child.ptr) |
52 |
|
10 |
shreduler_child(&tk->child); |
53 |
|
501 |
vector_rem2(&s->shreds, (vtype)tk->self); |
54 |
|
501 |
} |
55 |
|
|
|
56 |
|
512 |
ANN void shreduler_remove(const Shreduler s, const VM_Shred out, const m_bool erase) { |
57 |
|
512 |
MUTEX_LOCK(s->mutex); |
58 |
|
512 |
struct ShredTick_ *tk = out->tick; |
59 |
✓✓ |
512 |
if(tk == s->curr) |
60 |
|
489 |
s->curr = NULL; |
61 |
✓✓ |
23 |
else if(tk == s->list) |
62 |
|
7 |
s->list = tk->next; |
63 |
✓✓ |
512 |
if(tk->prev) |
64 |
|
15 |
tk->prev->next = tk->next; |
65 |
✓✓ |
512 |
if(tk->next) |
66 |
|
5 |
tk->next->prev = tk->prev; |
67 |
|
512 |
tk->prev = tk->next = NULL; |
68 |
✓✓ |
512 |
if(erase) { |
69 |
|
501 |
shreduler_erase(s, tk); |
70 |
|
501 |
_release(out->info->me, out); |
71 |
|
|
} |
72 |
|
512 |
MUTEX_UNLOCK(s->mutex); |
73 |
|
512 |
} |
74 |
|
|
|
75 |
|
668 |
ANN void shredule(const Shreduler s, const VM_Shred shred, const m_float wake_time) { |
76 |
|
668 |
const m_float time = wake_time + (m_float)s->bbq->pos; |
77 |
|
668 |
struct ShredTick_ *tk = shred->tick; |
78 |
|
668 |
tk->wake_time = time; |
79 |
✓✓ |
668 |
if(s->list) { |
80 |
|
178 |
struct ShredTick_ *curr = s->list, *prev = NULL; |
81 |
|
|
do { |
82 |
✓✓ |
624 |
if(curr->wake_time > time) |
83 |
|
72 |
break; |
84 |
|
552 |
prev = curr; |
85 |
✓✓ |
552 |
} while((curr = curr->next)); |
86 |
✓✓ |
178 |
if(!prev) { |
87 |
|
66 |
tk->next = s->list; |
88 |
|
66 |
s->list = (s->list->prev = tk); |
89 |
|
|
} else { |
90 |
✓✓ |
112 |
if((tk->next = prev->next)) |
91 |
|
6 |
prev->next->prev = tk; |
92 |
|
112 |
tk->prev = prev; |
93 |
|
112 |
prev->next = tk; |
94 |
|
|
} |
95 |
|
|
} else |
96 |
|
490 |
s->list = tk; |
97 |
✓✓ |
668 |
if(tk == s->curr) |
98 |
|
155 |
s->curr = NULL; |
99 |
|
668 |
} |
100 |
|
|
|
101 |
|
1219 |
ANN void shreduler_ini(const Shreduler s, const VM_Shred shred) { |
102 |
|
1219 |
shred->tick = mp_calloc(shred->info->mp, ShredTick); |
103 |
|
1219 |
shred->tick->self = shred; |
104 |
|
1219 |
shred->tick->shreduler = s; |
105 |
|
1219 |
} |
106 |
|
|
|
107 |
|
503 |
ANN void shreduler_add(const Shreduler s, const VM_Shred shred) { |
108 |
|
503 |
shreduler_ini(s, shred); |
109 |
|
503 |
shred->tick->xid = ++s->shred_ids; |
110 |
|
503 |
vector_add(&s->shreds, (vtype)shred); |
111 |
|
503 |
shredule(s, shred, GWION_EPSILON); |
112 |
|
503 |
} |