Imt.Base C++ API V4.1.1.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Dequeue.h
Go to the documentation of this file.
1// (c) IMT - Information Management Technology AG, CH-9470 Buchs, www.imt.ch.
2//
3// ActiveParts (AP) and the corresponding Data Flow Framework (DFF) is invented and designed by Jakob Daescher.
4// ANY USE OF THIS CODE CONSTITUTES ACCEPTANCE OF THE TERMS OF THE COPYRIGHT NOTICE.
5// ===================================================================================================
6// COPYRIGHT NOTICE
7// ===================================================================================================
8// Copyright (C) 2005-2075, IMT Information Management Technology AG, 9470 Buchs, Switzerland
9// All rights reserved.
10// This code is proprietary software of IMT Information Management Technology AG (hereinafter: "IMT").
11// Proprietary software is computer software licensed under exclusive legal right of IMT.
12//
13// The licensee is given the irrevocable, perpetual, worldwide, non-exclusive right and license to use,
14// execute and reproduce the software in binary form within the licensed products.
15//
16// Redistribution and use in source forms, without modification, are permitted provided that the following conditions are met:
17// (1) Copying of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
18// (2) Copying of source code is only allowed for regulatory documentation and archiving purposes
19// (3) Redistributions in binary form must reproduce the above copyright notice,
20// this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
21//
22// IMT provide no reassurances that the source code provided does not infringe
23// any patent, copyright, or any other intellectual property rights of third parties.
24// IMT disclaim any liability to any recipient for claims brought against
25// recipient by any third party for infringement of that parties intellectual property rights.
26//
27// THIS SOFTWARE IS PROVIDED BY IMT AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
28// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
29// IN NO EVENT SHALL IMT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
30// OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCURE-MENT OF SUBSTITUTE GOODS OR SERVICES;
31// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
32// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
33// IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34// ===================================================================================================
35#ifndef IMT_BASE_CORE_UTIL_DEQUEUE_H
36#define IMT_BASE_CORE_UTIL_DEQUEUE_H
37
38//AXIVION File Style CodingStyle-Naming.Method: function names similar to stl
39//AXIVION File Style AutosarC++19_03-M5.0.15: array indexing (or pointer arithmetic) required because does not own the buffer
40
43
44namespace imt {
45namespace base {
46namespace core {
47namespace util {
48
57template<typename T>
58class Dequeue final {
59public:
60
70 Dequeue(T* mem, uint16_t queueSize) noexcept;
71
78 void push_back(T const& e);
79
86 void push_front(T const& e);
87
92 void pop_front();
93
98 void pop_back();
99
107 T& front() {
108 return m_pMem[m_tail];
109 }
110
118 T const& front() const {
119 return m_pMem[m_tail];
120 }
121
129 T& back() {
130 return m_pMem[this->circularAddTo(m_head, m_queueSize - 1, m_queueSize)];
131 }
132
140 T const& back() const {
141 return m_pMem[this->circularAddTo(m_head, m_queueSize - 1, m_queueSize)];
142 }
143
149 size_t size() const;
150
156 bool empty() const {
157 // Not use multiple volatile statements in same c statement
158 // https://www.iar.com/knowledge/support/technical-notes/compiler/warningpa082-undefined-behavior-the-order-of-volatile-accesses-is-undefined-in-this-statement/
159 size_t const head {m_head};
160 size_t const tail {m_tail};
161
162 return head == tail;
163 }
164
170 bool full() const {
171 // Not use multiple volatile statements in same c statement
172 // https://www.iar.com/knowledge/support/technical-notes/compiler/warningpa082-undefined-behavior-the-order-of-volatile-accesses-is-undefined-in-this-statement/
173 size_t const add {this->circularAddTo(m_head, 1, m_queueSize)};
174 size_t const tail {m_tail};
175
176 return add == tail;
177 }
178
179private:
180
181 // Size of the queue.
182 size_t const m_queueSize;
183
184 // The queue memory.
185 T* m_pMem;
186
187 // Head index, points to the element right after the last written element.
188 // AXIVION Next Codeline AutosarC++19_03-A12.1.3: No NSDMI for only part of the members, all data members initialized in custom constructor
189 // AXIVION Next Codeline AutosarC++19_03-A2.11.1: volatile seems to be required here according to original implementer
190 size_t volatile m_head; // prevent optimizer from reordering
191
192 // Tail index, points to the element right after the last read element.
193 // AXIVION Next Codeline AutosarC++19_03-A12.1.3: No NSDMI for only part of the members, all data members initialized in custom constructor
194 // AXIVION Next Codeline AutosarC++19_03-A2.11.1: volatile seems to be required here according to original implementer
195 size_t volatile m_tail; // prevent optimizer from reordering
196
200 static size_t circularAddTo(size_t volatile to, size_t val, size_t size) { // AXIVION Line AutosarC++19_03-A2.11.1: volatile seems to be required here according to original implementer
201 return (to + val) % size;
202 }
203};
204
205// Implementation
206template<typename T>
207Dequeue<T>::Dequeue(T* mem, uint16_t queueSize) noexcept :
208 m_queueSize {queueSize},
209 m_pMem {mem},
210 m_head {0},
211 m_tail {0} {
212}
213
214template<typename T>
215void Dequeue<T>::push_back(T const& e) {
216 size_t const tmp {this->circularAddTo(m_head, 1, m_queueSize)}; // increment current head
217 if (tmp != m_tail) {
218 m_pMem[m_head] = e; // copy
219 m_head = tmp; // must be the last operation to finalize a change on the back of the queue.
220 }
221}
222
223template<typename T>
224void Dequeue<T>::push_front(T const& e) {
225 size_t const tmp {this->circularAddTo(m_tail, m_queueSize - 1, m_queueSize)}; // decrement current tail
226 if (tmp != m_head) {
227 m_pMem[tmp] = e; // copy
228 m_tail = tmp; // must be the last operation to finalize a change on the back of the queue.
229 }
230}
231
232template<typename T>
234 // Not use multiple volatile statements in same c statement
235 // https://www.iar.com/knowledge/support/technical-notes/compiler/warningpa082-undefined-behavior-the-order-of-volatile-accesses-is-undefined-in-this-statement/
236 size_t const head {m_head};
237 size_t const tail {m_tail};
238
239 if (tail != head) {
240 size_t const tmp {this->circularAddTo(m_tail, 1, m_queueSize)}; // increment current tail
241 m_tail = tmp; // must be the last operation to indicate a change on the front of the queue.
242 }
243}
244
245template<typename T>
247 // Not use multiple volatile statements in same c statement
248 // https://www.iar.com/knowledge/support/technical-notes/compiler/warningpa082-undefined-behavior-the-order-of-volatile-accesses-is-undefined-in-this-statement/
249 size_t const head {m_head};
250 size_t const tail {m_tail};
251
252 if (tail != head) {
253 size_t const tmp {this->circularAddTo(m_head, m_queueSize - 1, m_queueSize)}; // decrement current head
254 m_head = tmp; // must be the last operation to indicate a change on the back of the queue.
255 }
256}
257
258template<typename T>
259size_t Dequeue<T>::size() const {
260 size_t const tmpHead {m_head};
261 size_t const tmpTail {m_tail};
262
263 if (tmpHead >= tmpTail) {
264 return tmpHead - tmpTail;
265 }
266 else {
267 return (m_queueSize - tmpTail) + tmpHead;
268 }
269}
270
271} // namespace util
272} // namespace core
273} // namespace base
274} // namespace imt
275
276#endif // IMT_BASE_CORE_UTIL_DEQUEUE_H
Dequeue, Queue able to pop/push elements either from front or back.
Definition Dequeue.h:58
void pop_front()
Removes the front element of the queue.
Definition Dequeue.h:233
bool full() const
Returns if the queue is full.
Definition Dequeue.h:170
T const & back() const
Returns the back element of the queue.
Definition Dequeue.h:140
size_t size() const
Returns the current number of elements in the queue.
Definition Dequeue.h:259
void push_back(T const &e)
Adds a new element to the back of the queue.
Definition Dequeue.h:215
T const & front() const
Returns the front element of the queue.
Definition Dequeue.h:118
bool empty() const
Returns if the queue is empty.
Definition Dequeue.h:156
T & back()
Returns the back element of the queue.
Definition Dequeue.h:129
T & front()
Returns the front element of the queue.
Definition Dequeue.h:107
Dequeue(T *mem, uint16_t queueSize) noexcept
Constructor.
Definition Dequeue.h:207
void pop_back()
Removes the last element of the queue.
Definition Dequeue.h:246
void push_front(T const &e)
Adds a new element to the front of the queue.
Definition Dequeue.h:224
This is a application specific file which is used to configure Imt.Base.Core.Math.
unsigned __int16 uint16_t
Definition stdint.h:63