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 }