Merge branch 'upstreamedge' into fix/inverse-transform
[clinton/Smoothieware.git] / src / libs / HeapRing.cpp
1 #include "HeapRing.h"
2
3 #include <cstdlib>
4
5 #include "cmsis.h"
6
7 /*
8 * constructors
9 */
10
11 template<class kind> HeapRing<kind>::HeapRing()
12 {
13 head_i = tail_i = length = 0;
14 isr_tail_i = tail_i;
15 ring = NULL;
16 }
17
18 template<class kind> HeapRing<kind>::HeapRing(unsigned int length)
19 {
20 head_i = tail_i = 0;
21 isr_tail_i = tail_i;
22 ring = new kind[length];
23 // TODO: handle allocation failure
24 this->length = length;
25 }
26
27 /*
28 * destructor
29 */
30
31 template<class kind> HeapRing<kind>::~HeapRing()
32 {
33 head_i = tail_i = length = 0;
34 isr_tail_i = tail_i;
35 if (ring)
36 delete [] ring;
37 ring = NULL;
38 }
39
40 /*
41 * index accessors (protected)
42 */
43
44 template<class kind> unsigned int HeapRing<kind>::next(unsigned int item) const
45 {
46 if (length == 0)
47 return 0;
48
49 if (++item >= length)
50 return 0;
51
52 return item;
53 }
54
55 template<class kind> unsigned int HeapRing<kind>::prev(unsigned int item) const
56 {
57 if (length == 0)
58 return 0;
59
60 if (item == 0)
61 return (length - 1);
62 else
63 return (item - 1);
64 }
65
66 /*
67 * reference accessors
68 */
69
70 template<class kind> kind& HeapRing<kind>::head()
71 {
72 return ring[head_i];
73 }
74
75 template<class kind> kind& HeapRing<kind>::tail()
76 {
77 return ring[tail_i];
78 }
79
80 template<class kind> kind& HeapRing<kind>::item(unsigned int i)
81 {
82 return ring[i];
83 }
84
85 template<class kind> void HeapRing<kind>::push_front(kind& item)
86 {
87 ring[head_i] = item;
88 head_i = next(head_i);
89 }
90
91 template<class kind> kind& HeapRing<kind>::pop_back()
92 {
93 kind& r = ring[tail_i];
94 tail_i = next(tail_i);
95 return r;
96 }
97
98 /*
99 * pointer accessors
100 */
101
102 template<class kind> kind* HeapRing<kind>::head_ref()
103 {
104 return &ring[head_i];
105 }
106
107 template<class kind> kind* HeapRing<kind>::tail_ref()
108 {
109 return &ring[tail_i];
110 }
111
112 template<class kind> kind* HeapRing<kind>::item_ref(unsigned int i)
113 {
114 return &ring[i];
115 }
116
117 template<class kind> void HeapRing<kind>::produce_head()
118 {
119 while (is_full());
120 head_i = next(head_i);
121 }
122
123 template<class kind> void HeapRing<kind>::consume_tail()
124 {
125 if (!is_empty())
126 tail_i = next(tail_i);
127 }
128
129 /*
130 * queue status accessors
131 */
132
133 template<class kind> bool HeapRing<kind>::is_full() const
134 {
135 //__disable_irq();
136 bool r = (next(head_i) == tail_i);
137 //__enable_irq();
138
139 return r;
140 }
141
142 template<class kind> bool HeapRing<kind>::is_empty() const
143 {
144 //__disable_irq();
145 bool r = (head_i == tail_i);
146 //__enable_irq();
147
148 return r;
149 }
150
151 /*
152 * resize
153 */
154
155 template<class kind> bool HeapRing<kind>::resize(unsigned int length)
156 {
157 if (is_empty())
158 {
159 if (length == 0)
160 {
161 __disable_irq();
162
163 if (is_empty()) // check again in case something was pushed
164 {
165 head_i = tail_i = this->length = 0;
166
167 __enable_irq();
168
169 if (ring)
170 delete [] ring;
171 ring = NULL;
172
173 return true;
174 }
175
176 __enable_irq();
177
178 return false;
179 }
180
181 // Note: we don't use realloc so we can fall back to the existing ring if allocation fails
182 kind* newring = new kind[length];
183
184 if (newring != NULL)
185 {
186 kind* oldring = ring;
187
188 __disable_irq();
189
190 if (is_empty()) // check again in case something was pushed while malloc did its thing
191 {
192 ring = newring;
193 this->length = length;
194 head_i = tail_i = 0;
195
196 __enable_irq();
197
198 if (oldring)
199 delete [] oldring;
200
201 return true;
202 }
203
204 __enable_irq();
205
206 delete [] newring;
207 }
208 }
209
210 return false;
211 }
212
213 template<class kind> bool HeapRing<kind>::provide(kind* buffer, unsigned int length)
214 {
215 __disable_irq();
216
217 if (is_empty())
218 {
219 kind* oldring = ring;
220
221 if ((buffer != NULL) && (length > 0))
222 {
223 ring = buffer;
224 this->length = length;
225 head_i = tail_i = 0;
226
227 __enable_irq();
228
229 if (oldring)
230 delete [] oldring;
231 return true;
232 }
233 }
234
235 __enable_irq();
236
237 return false;
238 }