Mercurial > hg > beaglert
comparison projects/heavy/hello-world/MessageQueue.c @ 160:5bcf04234f80 heavy-updated
- added -std=c99 to Makefile for user-supplied C files (required for heavy files)
- changed heavy core render.cpp file to use latest API and removed all redundant functions (e.g. foleyDesigner/touchkey stuff)
- use build_pd.sh to compile and run pd files (-h for usage instructions)
author | chnrx <chris.heinrichs@gmail.com> |
---|---|
date | Thu, 05 Nov 2015 18:58:26 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
159:1e7db6610600 | 160:5bcf04234f80 |
---|---|
1 /** | |
2 * Copyright (c) 2014, 2015, Enzien Audio Ltd. | |
3 * | |
4 * Permission to use, copy, modify, and/or distribute this software for any | |
5 * purpose with or without fee is hereby granted, provided that the above | |
6 * copyright notice and this permission notice appear in all copies. | |
7 * | |
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH | |
9 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY | |
10 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, | |
11 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM | |
12 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR | |
13 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR | |
14 * PERFORMANCE OF THIS SOFTWARE. | |
15 */ | |
16 | |
17 #include "MessageQueue.h" | |
18 #include "Utils.h" | |
19 | |
20 hv_size_t mq_init(MessageQueue *q) { | |
21 q->head = NULL; | |
22 q->tail = NULL; | |
23 q->pool = NULL; | |
24 return mp_init(&q->mp, 1); | |
25 } | |
26 | |
27 void mq_initWithPoolSize(MessageQueue *q, hv_size_t poolSizeKB) { | |
28 q->head = NULL; | |
29 q->tail = NULL; | |
30 q->pool = NULL; | |
31 mp_init(&q->mp, poolSizeKB); | |
32 } | |
33 | |
34 void mq_free(MessageQueue *q) { | |
35 mq_clear(q); | |
36 while (q->pool != NULL) { | |
37 MessageNode *n = q->pool; | |
38 q->pool = q->pool->next; | |
39 hv_free(n); | |
40 } | |
41 mp_free(&q->mp); | |
42 } | |
43 | |
44 static MessageNode *mq_getOrCreateNodeFromPool(MessageQueue *q) { | |
45 if (q->pool == NULL) { | |
46 // if necessary, create a new empty node | |
47 q->pool = (MessageNode *) hv_malloc(sizeof(MessageNode)); | |
48 q->pool->next = NULL; | |
49 } | |
50 MessageNode *node = q->pool; | |
51 q->pool = q->pool->next; | |
52 return node; | |
53 } | |
54 | |
55 int mq_size(MessageQueue *q) { | |
56 int size = 0; | |
57 MessageNode *n = q->head; | |
58 while (n != NULL) { | |
59 ++size; | |
60 n = n->next; | |
61 } | |
62 return size; | |
63 } | |
64 | |
65 HvMessage *mq_addMessage(MessageQueue *q, const HvMessage *m, int let, | |
66 void (*sendMessage)(struct HvBase *, int, const HvMessage *)) { | |
67 MessageNode *node = mq_getOrCreateNodeFromPool(q); | |
68 node->m = mp_addMessage(&q->mp, m); | |
69 node->let = let; | |
70 node->sendMessage = sendMessage; | |
71 node->prev = NULL; | |
72 node->next = NULL; | |
73 | |
74 if (q->tail != NULL) { | |
75 // the list already contains elements | |
76 q->tail->next = node; | |
77 node->prev = q->tail; | |
78 q->tail = node; | |
79 } else { | |
80 // the list is empty | |
81 node->prev = NULL; | |
82 q->head = node; | |
83 q->tail = node; | |
84 } | |
85 return mq_node_getMessage(node); | |
86 } | |
87 | |
88 HvMessage *mq_addMessageByTimestamp(MessageQueue *q, HvMessage *m, int let, | |
89 void (*sendMessage)(struct HvBase *, int, const HvMessage *)) { | |
90 if (mq_hasMessage(q)) { | |
91 MessageNode *n = mq_getOrCreateNodeFromPool(q); | |
92 n->m = mp_addMessage(&q->mp, m); | |
93 n->let = let; | |
94 n->sendMessage = sendMessage; | |
95 | |
96 if (msg_getTimestamp(m) < msg_getTimestamp(q->head->m)) { | |
97 // the message occurs before the current head | |
98 n->next = q->head; | |
99 q->head->prev = n; | |
100 n->prev = NULL; | |
101 q->head = n; | |
102 } else if (msg_getTimestamp(m) >= msg_getTimestamp(q->tail->m)) { | |
103 // the message occurs after the current tail | |
104 n->next = NULL; | |
105 n->prev = q->tail; | |
106 q->tail->next = n; | |
107 q->tail = n; | |
108 } else { | |
109 // the message occurs somewhere between the head and tail | |
110 MessageNode *node = q->head; | |
111 while (node != NULL) { | |
112 if (m->timestamp < msg_getTimestamp(node->next->m)) { | |
113 MessageNode *r = node->next; | |
114 node->next = n; | |
115 n->next = r; | |
116 n->prev = node; | |
117 r->prev = n; | |
118 break; | |
119 } | |
120 node = node->next; | |
121 } | |
122 } | |
123 return n->m; | |
124 } else { | |
125 // add a message to the head | |
126 return mq_addMessage(q, m, let, sendMessage); | |
127 } | |
128 } | |
129 | |
130 void mq_pop(MessageQueue *q) { | |
131 if (mq_hasMessage(q)) { | |
132 MessageNode *n = q->head; | |
133 | |
134 mp_freeMessage(&q->mp, n->m); | |
135 n->m = NULL; | |
136 | |
137 n->let = 0; | |
138 n->sendMessage = NULL; | |
139 | |
140 q->head = n->next; | |
141 if (q->head == NULL) { | |
142 q->tail = NULL; | |
143 } else { | |
144 q->head->prev = NULL; | |
145 } | |
146 n->next = q->pool; | |
147 n->prev = NULL; | |
148 q->pool = n; | |
149 } | |
150 } | |
151 | |
152 void mq_removeMessage(MessageQueue *q, HvMessage *m, void (*sendMessage)(struct HvBase *, int, const HvMessage *)) { | |
153 if (mq_hasMessage(q)) { | |
154 if (mq_node_getMessage(q->head) == m) { // msg in head node | |
155 // only remove the message if sendMessage is the same as the stored one, | |
156 // if the sendMessage argument is NULL, it is not checked and will remove any matching message pointer | |
157 if (sendMessage == NULL || q->head->sendMessage == sendMessage) { | |
158 mq_pop(q); | |
159 } | |
160 } else { | |
161 MessageNode *prevNode = q->head; | |
162 MessageNode *currNode = q->head->next; | |
163 while ((currNode != NULL) && (currNode->m != m)) { | |
164 prevNode = currNode; | |
165 currNode = currNode->next; | |
166 } | |
167 if (currNode != NULL) { | |
168 if (sendMessage == NULL || currNode->sendMessage == sendMessage) { | |
169 mp_freeMessage(&q->mp, m); | |
170 currNode->m = NULL; | |
171 currNode->let = 0; | |
172 currNode->sendMessage = NULL; | |
173 if (currNode == q->tail) { // msg in tail node | |
174 prevNode->next = NULL; | |
175 q->tail = prevNode; | |
176 } else { // msg in middle node | |
177 prevNode->next = currNode->next; | |
178 currNode->next->prev = prevNode; | |
179 } | |
180 currNode->next = (q->pool == NULL) ? NULL : q->pool; | |
181 currNode->prev = NULL; | |
182 q->pool = currNode; | |
183 } | |
184 } | |
185 } | |
186 } | |
187 } | |
188 | |
189 void mq_clear(MessageQueue *q) { | |
190 while (mq_hasMessage(q)) { | |
191 mq_pop(q); | |
192 } | |
193 } | |
194 | |
195 void mq_clearAfter(MessageQueue *q, const double timestamp) { | |
196 MessageNode *n = q->tail; | |
197 while (n != NULL && timestamp <= msg_getTimestamp(n->m)) { | |
198 // free the node's message | |
199 mp_freeMessage(&q->mp, n->m); | |
200 n->m = NULL; | |
201 n->let = 0; | |
202 n->sendMessage = NULL; | |
203 | |
204 // the tail points at the previous node | |
205 q->tail = n->prev; | |
206 | |
207 // put the node back in the pool | |
208 n->next = q->pool; | |
209 n->prev = NULL; | |
210 if (q->pool != NULL) q->pool->prev = n; | |
211 q->pool = n; | |
212 | |
213 // update the tail node | |
214 n = q->tail; | |
215 } | |
216 | |
217 if (q->tail == NULL) q->head = NULL; | |
218 } |