Allow M18 to turn off selected motors
[clinton/Smoothieware.git] / src / libs / HeapRing.cpp
CommitLineData
cc1e352c
MM
1#include "HeapRing.h"
2
3#include <cstdlib>
4
5#include "cmsis.h"
6
7/*
8 * constructors
9 */
10
11template<class kind> HeapRing<kind>::HeapRing()
12{
13 head_i = tail_i = length = 0;
f6542ad9 14 isr_tail_i = tail_i;
cc1e352c
MM
15 ring = NULL;
16}
17
18template<class kind> HeapRing<kind>::HeapRing(unsigned int length)
19{
20 head_i = tail_i = 0;
f6542ad9 21 isr_tail_i = tail_i;
cc1e352c
MM
22 ring = new kind[length];
23 // TODO: handle allocation failure
24 this->length = length;
25}
26
27/*
28 * destructor
29 */
30
31template<class kind> HeapRing<kind>::~HeapRing()
32{
33 head_i = tail_i = length = 0;
f6542ad9 34 isr_tail_i = tail_i;
cc1e352c
MM
35 if (ring)
36 delete [] ring;
37 ring = NULL;
38}
39
40/*
41 * index accessors (protected)
42 */
43
b5708347 44template<class kind> unsigned int HeapRing<kind>::next(unsigned int item) const
cc1e352c
MM
45{
46 if (length == 0)
47 return 0;
48
49 if (++item >= length)
50 return 0;
51
52 return item;
53}
54
b5708347 55template<class kind> unsigned int HeapRing<kind>::prev(unsigned int item) const
cc1e352c
MM
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
70template<class kind> kind& HeapRing<kind>::head()
71{
72 return ring[head_i];
73}
74
75template<class kind> kind& HeapRing<kind>::tail()
76{
77 return ring[tail_i];
78}
79
80template<class kind> kind& HeapRing<kind>::item(unsigned int i)
81{
82 return ring[i];
83}
84
85template<class kind> void HeapRing<kind>::push_front(kind& item)
86{
87 ring[head_i] = item;
88 head_i = next(head_i);
89}
90
91template<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
102template<class kind> kind* HeapRing<kind>::head_ref()
103{
104 return &ring[head_i];
105}
106
107template<class kind> kind* HeapRing<kind>::tail_ref()
108{
109 return &ring[tail_i];
110}
111
112template<class kind> kind* HeapRing<kind>::item_ref(unsigned int i)
113{
114 return &ring[i];
115}
116
117template<class kind> void HeapRing<kind>::produce_head()
118{
1b918dbb 119 while (is_full());
cc1e352c
MM
120 head_i = next(head_i);
121}
122
123template<class kind> void HeapRing<kind>::consume_tail()
124{
1b918dbb
MM
125 if (!is_empty())
126 tail_i = next(tail_i);
cc1e352c
MM
127}
128
129/*
130 * queue status accessors
131 */
132
b5708347 133template<class kind> bool HeapRing<kind>::is_full() const
cc1e352c 134{
2a7a3136 135 //__disable_irq();
1b918dbb 136 bool r = (next(head_i) == tail_i);
2a7a3136 137 //__enable_irq();
1b918dbb
MM
138
139 return r;
cc1e352c
MM
140}
141
b5708347 142template<class kind> bool HeapRing<kind>::is_empty() const
cc1e352c 143{
2a7a3136 144 //__disable_irq();
1b918dbb 145 bool r = (head_i == tail_i);
2a7a3136 146 //__enable_irq();
1b918dbb
MM
147
148 return r;
cc1e352c
MM
149}
150
151/*
152 * resize
153 */
154
155template<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
b6691e01
MM
169 if (ring)
170 delete [] ring;
cc1e352c
MM
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
213template<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}