Friendly LWM2M client
SafeQueue< T, SIZE > Class Template Reference

SafeQueue is an implementation of the thread/IRQ safe queue that does not use dynamic memory, and can perform sumultaneously pop() and push() without any blocking, that alows use this implementation as data container in the critical sections, or threads and IRQ where it is impossible to wait for access to the container and data loss is unacceptable. Developed with a focus on embedded systems. More...

#include <SafeQueue.h>

+ Collaboration diagram for SafeQueue< T, SIZE >:

Public Member Functions

 SafeQueue ()
 
bool push (const T *const data, size_t elements_cnt=SAFE_QUEUE_DEF_ELEM_CNT)
 Adds an element or an array of elements to the queue. The push() method can be simultaneously called with the pop() method from different threads, but simultaneous calls to push() from the same thread are prohibited and protected by the guard. Adding an element(s) to the queue is done via a byte-by-byte copy, so the data type must be simple. More...
 
bool pop (size_t elements_cnt=SAFE_QUEUE_DEF_ELEM_CNT)
 Removes a specified number of elements from the queue. The pop() method can be simultaneously called with the push() method from different threads, but simultaneous calls to pop() from the same thread are prohibited and protected by the guard. More...
 
std::vector< T > to_vector (size_t elements_cnt=SIZE)
 Converts the contents of the queue to a vector. The to_vector() method creates a vector containing a specified number of elements from the queue. More...
 
T * front ()
 Returns a pointer to the first element in the queue. The front() method does not guarantee that the pointer to the data after the return will still be correct if after or during this call will be called pop(). More...
 
T * back ()
 Returns a pointer to the last element in the queue. The back() method does not guarantee that the pointer to the data after the return will still be correct if after or during this call will be called pop(). More...
 
T * at (size_t i)
 Returns a pointer to the element at the specified index in the queue. The at() method does not guarantee that the pointer to the data after the return will still be correct if after or during this call will be called pop(). More...
 
bool front (T *data)
 Returns the first element in the queue and copies it to the specified memory location. The front() method can guarantee the integrity of the data and ensures that it corresponds to what was written to the queue. The user needs to pass a pointer to the memory allocated for this type. More...
 
bool back (T *data)
 Returns the last element in the queue and copies it to the specified memory location. The back() method can guarantee the integrity of the data and ensures that it corresponds to what was written to the queue. The user needs to pass a pointer to the memory allocated for this type. More...
 
bool at (size_t i, T *data)
 Returns the element at the specified index in the queue and copies it to the specified memory location. The at() method can guarantee the integrity of the data and ensures that it corresponds to what was written to the queue. The user needs to pass a pointer to the memory allocated for this type. More...
 
void clear ()
 Clears the queue. More...
 
bool is_empty ()
 Checks if the queue is empty. More...
 
bool is_full ()
 Checks if the queue is full. More...
 
size_t size ()
 Returns the current size of the queue. More...
 
size_t available_space ()
 Returns the number of additional elements the queue can hold. More...
 
uint32_t element_size ()
 Returns the size of each element in the queue. More...
 

Detailed Description

template<typename T, size_t SIZE>
class SafeQueue< T, SIZE >

SafeQueue is an implementation of the thread/IRQ safe queue that does not use dynamic memory, and can perform sumultaneously pop() and push() without any blocking, that alows use this implementation as data container in the critical sections, or threads and IRQ where it is impossible to wait for access to the container and data loss is unacceptable. Developed with a focus on embedded systems.

The problem it solves is the following: it is necessary to have a container that allows adding and removing elements independently by different streams/ISR. This container is protected from the simultaneous call of the push/pop method from the same threads, and allows the simultaneous call of push and pop from different threads without internal blocking, that is, if an interruption occurred that interrupted the removal process, it can easily perform addition or vice versa. For example, if there is an interrupt in which you need to add an element to the queue and there is a main loop that removes elements from the queue, if you use standard containers, then to use them in the main loop, you must first ensure access synchronization so that the internal state is not changed if an interruption occurs, but in this case, if an interrupt occurs at this time, it will not be able to access the container until the main loop releases the mutex, which in turn leads to data loss.

Definition at line 99 of file SafeQueue.h.

Constructor & Destructor Documentation

◆ SafeQueue()

template<typename T , size_t SIZE>
SafeQueue< T, SIZE >::SafeQueue ( )
inline

Definition at line 101 of file SafeQueue.h.

Member Function Documentation

◆ at() [1/2]

template<typename T , size_t SIZE>
T * SafeQueue< T, SIZE >::at ( size_t  i)

Returns a pointer to the element at the specified index in the queue. The at() method does not guarantee that the pointer to the data after the return will still be correct if after or during this call will be called pop().

Parameters
i- The index of the element.
Returns
A pointer to the element at the specified index in the queue.

Definition at line 354 of file SafeQueue.h.

◆ at() [2/2]

template<typename T , size_t SIZE>
bool SafeQueue< T, SIZE >::at ( size_t  i,
T *  data 
)

Returns the element at the specified index in the queue and copies it to the specified memory location. The at() method can guarantee the integrity of the data and ensures that it corresponds to what was written to the queue. The user needs to pass a pointer to the memory allocated for this type.

Note
Can not be simultaneously called with pop(), to_vector(), front(T*), back(T*), at(T*).
Parameters
i- The index of the element.
data- Pointer to the memory location where the element will be copied.
Returns
true if the element at the specified index was successfully copied to the specified memory location, false otherwise.

Definition at line 388 of file SafeQueue.h.

◆ available_space()

template<typename T , size_t SIZE>
size_t SafeQueue< T, SIZE >::available_space

Returns the number of additional elements the queue can hold.

Calculates the remaining capacity of the queue, which is the difference between the queue's maximum capacity and its current size.

Returns
Available space in the queue.

Definition at line 422 of file SafeQueue.h.

◆ back() [1/2]

template<typename T , size_t SIZE>
T * SafeQueue< T, SIZE >::back

Returns a pointer to the last element in the queue. The back() method does not guarantee that the pointer to the data after the return will still be correct if after or during this call will be called pop().

Returns
A pointer to the last element in the queue.

Definition at line 348 of file SafeQueue.h.

◆ back() [2/2]

template<typename T , size_t SIZE>
bool SafeQueue< T, SIZE >::back ( T *  data)

Returns the last element in the queue and copies it to the specified memory location. The back() method can guarantee the integrity of the data and ensures that it corresponds to what was written to the queue. The user needs to pass a pointer to the memory allocated for this type.

Note
Can not be simultaneously called with pop(), to_vector(), front(T*), back(T*), at(T*).
Parameters
data- Pointer to the memory location where the last element will be copied.
Returns
true if the last element was successfully copied to the specified memory location, false otherwise.

Definition at line 374 of file SafeQueue.h.

◆ clear()

template<typename T , size_t SIZE>
void SafeQueue< T, SIZE >::clear

Clears the queue.

Note
Can not be simultaneously called with pop(), to_vector(), front(T*), back(T*), at(T*).

Definition at line 402 of file SafeQueue.h.

◆ element_size()

template<typename T , size_t SIZE>
uint32_t SafeQueue< T, SIZE >::element_size

Returns the size of each element in the queue.

Returns
The size of each element in the queue.

Definition at line 427 of file SafeQueue.h.

◆ front() [1/2]

template<typename T , size_t SIZE>
T * SafeQueue< T, SIZE >::front

Returns a pointer to the first element in the queue. The front() method does not guarantee that the pointer to the data after the return will still be correct if after or during this call will be called pop().

Returns
A pointer to the first element in the queue.

Definition at line 342 of file SafeQueue.h.

◆ front() [2/2]

template<typename T , size_t SIZE>
bool SafeQueue< T, SIZE >::front ( T *  data)

Returns the first element in the queue and copies it to the specified memory location. The front() method can guarantee the integrity of the data and ensures that it corresponds to what was written to the queue. The user needs to pass a pointer to the memory allocated for this type.

Note
Can not be simultaneously called with pop(), to_vector(), front(T*), back(T*), at(T*).
Parameters
data- Pointer to the memory location where the first element will be copied.
Returns
true if the first element was successfully copied to the specified memory location, false otherwise.

Definition at line 360 of file SafeQueue.h.

◆ is_empty()

template<typename T , size_t SIZE>
bool SafeQueue< T, SIZE >::is_empty

Checks if the queue is empty.

Returns
true if the queue is empty, false otherwise.

Definition at line 407 of file SafeQueue.h.

◆ is_full()

template<typename T , size_t SIZE>
bool SafeQueue< T, SIZE >::is_full

Checks if the queue is full.

Returns
true if the queue is full, false otherwise.

Definition at line 412 of file SafeQueue.h.

◆ pop()

template<typename T , size_t SIZE>
bool SafeQueue< T, SIZE >::pop ( size_t  elements_cnt = SAFE_QUEUE_DEF_ELEM_CNT)

Removes a specified number of elements from the queue. The pop() method can be simultaneously called with the push() method from different threads, but simultaneous calls to pop() from the same thread are prohibited and protected by the guard.

Parameters
elements_cnt- Number of elements to be removed from the queue.
Returns
true if the elements were successfully removed from the queue, false otherwise.

Definition at line 297 of file SafeQueue.h.

◆ push()

template<typename T , size_t SIZE>
bool SafeQueue< T, SIZE >::push ( const T *const  data,
size_t  elements_cnt = SAFE_QUEUE_DEF_ELEM_CNT 
)

Adds an element or an array of elements to the queue. The push() method can be simultaneously called with the pop() method from different threads, but simultaneous calls to push() from the same thread are prohibited and protected by the guard. Adding an element(s) to the queue is done via a byte-by-byte copy, so the data type must be simple.

Parameters
data- Pointer to the data to be added to the queue.
elements_cnt- Number of elements to be added to the queue if data is an array.
Returns
true if the data was successfully added to the queue, false otherwise.

Definition at line 277 of file SafeQueue.h.

◆ size()

template<typename T , size_t SIZE>
size_t SafeQueue< T, SIZE >::size

Returns the current size of the queue.

Returns
The current size of the queue.

Definition at line 417 of file SafeQueue.h.

◆ to_vector()

template<typename T , size_t SIZE>
std::vector< T > SafeQueue< T, SIZE >::to_vector ( size_t  elements_cnt = SIZE)

Converts the contents of the queue to a vector. The to_vector() method creates a vector containing a specified number of elements from the queue.

Note
Can not be simultaneously called with pop(), to_vector(), front(T*), back(T*), at(T*).
Parameters
elements_cnt- Number of elements to be included in the vector.
Returns
A vector containing the specified number of elements from the queue.

Available two potential situations: 1) Elements range placed between _front_i and SIZE 2) Elements range placed between _front_i -> SIZE and 0 -> end_of_range_index

If is_out_of_range set to true then we have second situation, and converting operation will be performed in two steps

Definition at line 314 of file SafeQueue.h.