Skip to content

Commit d7d5da2

Browse files
committed
Added a basic rtos queue
1 parent 8875f3d commit d7d5da2

File tree

1 file changed

+192
-0
lines changed

1 file changed

+192
-0
lines changed

rtos/queue.hpp

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
#ifndef KLIB_RTOS_QUEUE_HPP
2+
#define KLIB_RTOS_QUEUE_HPP
3+
4+
#include <atomic>
5+
6+
#include <klib/ringbuffer.hpp>
7+
8+
#include "waitable.hpp"
9+
#include "mutex.hpp"
10+
11+
namespace klib::rtos {
12+
/**
13+
* @brief Queue class for RTOS usage implemented using a ringbuffer
14+
*
15+
* @tparam Size
16+
*/
17+
template <typename T, size_t MaxSize>
18+
class queue: public waitable {
19+
protected:
20+
std::atomic_bool waiting;
21+
22+
// mutex to protect access to the queue
23+
rtos::mutex mutex;
24+
25+
// ringbuffer to store the data
26+
klib::ringbuffer<T, MaxSize> buffer;
27+
28+
public:
29+
/**
30+
* @brief Add an item to the queue.
31+
*
32+
* @param val
33+
*/
34+
constexpr void push(const T &val) {
35+
mutex.lock();
36+
37+
// wait until we have space in the buffer
38+
while (buffer.full()) {
39+
// mark as waiting
40+
waiting.store(true);
41+
42+
// unlock the mutex while waiting
43+
mutex.unlock();
44+
45+
// yield to other tasks
46+
rtos::syscall::yield(*this);
47+
48+
// lock the mutex again
49+
mutex.lock();
50+
}
51+
52+
// push the item to the buffer
53+
buffer.push(val);
54+
55+
// clear the waiting flag for the other side if it was waiting
56+
// on data to be available in the buffer
57+
waiting.store(false);
58+
59+
// unlock the mutex
60+
mutex.unlock();
61+
}
62+
63+
/**
64+
* @brief Copy the last item from the buffer and pop.
65+
*
66+
* @return
67+
*/
68+
constexpr T copy_and_pop() {
69+
// lock the mutex while accessing the buffer
70+
mutex.lock();
71+
72+
// wait until we have data in the buffer
73+
while (buffer.empty()) {
74+
// mark as waiting
75+
waiting.store(true);
76+
77+
// unlock the mutex while waiting
78+
mutex.unlock();
79+
80+
// yield to other tasks
81+
rtos::syscall::yield(*this);
82+
83+
// lock the mutex again
84+
mutex.lock();
85+
}
86+
87+
// copy and pop the item
88+
T item = buffer.copy_and_pop();
89+
90+
// clear the waiting flag for the other side if it was waiting
91+
// on space in the buffer
92+
waiting.store(false);
93+
94+
// unlock the mutex
95+
mutex.unlock();
96+
97+
// return the item
98+
return item;
99+
}
100+
101+
/**
102+
* @brief clear the queue.
103+
*
104+
* @return
105+
*/
106+
constexpr void clear() {
107+
// lock the mutex while clearing the buffer
108+
mutex.lock();
109+
110+
// clear the buffer
111+
buffer.clear();
112+
113+
// unlock the mutex
114+
mutex.unlock();
115+
}
116+
117+
/**
118+
* @brief Return whether the queue is empty.
119+
*
120+
* @return
121+
*/
122+
constexpr bool empty() {
123+
// lock the mutex while accessing the buffer
124+
mutex.lock();
125+
126+
// check if the buffer is empty
127+
const bool is_empty = buffer.empty();
128+
129+
// unlock the mutex
130+
mutex.unlock();
131+
132+
return is_empty;
133+
}
134+
135+
/**
136+
* @brief Return whether the queue is full.
137+
*
138+
* @return
139+
*/
140+
constexpr bool full() {
141+
// lock the mutex while accessing the buffer
142+
mutex.lock();
143+
144+
// check if the buffer is full
145+
const bool is_full = buffer.full();
146+
147+
// unlock the mutex
148+
mutex.unlock();
149+
150+
return is_full;
151+
}
152+
153+
/**
154+
* @brief Get the current size of the queue.
155+
*
156+
* @return
157+
*/
158+
constexpr size_t size() {
159+
// lock the mutex while accessing the buffer
160+
mutex.lock();
161+
162+
// get the size of the buffer
163+
const size_t current_size = buffer.size();
164+
165+
// unlock the mutex
166+
mutex.unlock();
167+
168+
return current_size;
169+
}
170+
171+
/**
172+
* @brief Get the maximum size of the queue.
173+
*
174+
* @return
175+
*/
176+
constexpr size_t max_size() const {
177+
return MaxSize;
178+
}
179+
180+
/**
181+
* @brief
182+
*
183+
* @return true
184+
* @return false
185+
*/
186+
virtual bool is_waiting() const override {
187+
return waiting.load();
188+
}
189+
};
190+
}
191+
192+
#endif

0 commit comments

Comments
 (0)