Open Model Railroad Network (OpenMRN)
Loading...
Searching...
No Matches
DeviceBuffer.hxx
Go to the documentation of this file.
1
35#ifndef _FREERTOS_DRIVERS_COMMON_DEVICE_BUFFER_HXX_
36#define _FREERTOS_DRIVERS_COMMON_DEVICE_BUFFER_HXX_
37
38#include <new>
39#include <cstdint>
40#include <unistd.h>
41#include <stdlib.h>
42
43#include "openmrn_features.h"
44#include "utils/macros.h"
45
46#ifdef OPENMRN_FEATURE_DEVTAB
47#include "Devtab.hxx"
48#endif // OPENMRN_FEATURE_DEVTAB
49
53{
54public:
55#ifdef OPENMRN_FEATURE_DEVTAB
60 static void block_until_condition(File *file, bool read);
61#endif // OPENMRN_FEATURE_DEVTAB
62
66 {
67#ifdef OPENMRN_FEATURE_DEVTAB
68 Device::select_wakeup(&selectInfo);
69#endif // OPENMRN_FEATURE_DEVTAB
70 }
71
76 {
77#ifdef OPENMRN_FEATURE_DEVTAB
78 int woken = 0;
79 Device::select_wakeup_from_isr(&selectInfo, &woken);
80#endif // OPENMRN_FEATURE_DEVTAB
81 }
82
88 void flush()
89 {
90 count = 0;
91 readIndex = 0;
92 writeIndex = 0;
93 }
94
98 size_t pending()
99 {
100 return count;
101 }
102
106 size_t space()
107 {
108 return size - count;
109 }
110
114 {
115#ifdef OPENMRN_FEATURE_DEVTAB
116 return Device::select_insert(&selectInfo);
117#endif // OPENMRN_FEATURE_DEVTAB
118 }
119
124 size_t consume(size_t items)
125 {
126 if (items > count)
127 {
128 items = count;
129 }
130 size_t consumed = items;
131 count -= items;
132 if ((readIndex + items) >= size)
133 {
134 items -= (size - readIndex);
135 readIndex = 0;
136 }
137 readIndex += items;
138
139 return consumed;
140 }
141
146 size_t advance(size_t items)
147 {
148 if (items > space())
149 {
150 items = space();
151 }
152 size_t added = items;
153 count += items;
154 if ((writeIndex + items) >= size)
155 {
156 items -= (size - writeIndex);
157 writeIndex = 0;
158 }
159 writeIndex += items;
160
161 return added;
162 }
163
164protected:
171 : level(level)
172 , size(size)
173 , count(0)
174 , readIndex(0)
175 , writeIndex(0)
176 {
177 }
178
182 {
183 }
184
185#ifdef OPENMRN_FEATURE_DEVTAB
187 Device::SelectInfo selectInfo;
188#endif // OPENMRN_FEATURE_DEVTAB
189
191 uint16_t level;
192
194 uint16_t size;
195
197 uint16_t count;
198
200 uint16_t readIndex;
201
203 uint16_t writeIndex;
204
205private:
207};
208
215template <typename T> class DeviceBuffer : public DeviceBufferBase
216{
217public:
224 static DeviceBuffer *create(size_t size, size_t level = 0)
225 {
226 HASSERT(size <= UINT16_MAX);
227 HASSERT(level <= size);
228 DeviceBuffer *device_buffer =
229 (DeviceBuffer*)malloc(sizeof(DeviceBuffer) + (size * sizeof(T)));
230 /* placement new allows for runtime ring buffer size */
231 new (device_buffer) DeviceBuffer(size, level);
232
233 return device_buffer;
234 }
235
236 typedef T member_type;
237
239 static constexpr unsigned member_size()
240 {
241 return sizeof(T);
242 }
243
244
245
248 void destroy()
249 {
250 free(this);
251 }
252
258 size_t put(const T *buf, size_t items)
259 {
260 size_t last_count = count;
261
262 while (items && (count < size))
263 {
264 data[writeIndex++] = *buf++;
265 if (writeIndex == size)
266 {
267 writeIndex = 0;
268 }
269 ++count;
270 --items;
271 }
272
273 return count - last_count;
274 }
275
281 size_t get(T *buf, size_t items)
282 {
283 size_t last_count = count;
284
285 while (items && (count > 0))
286 {
287 *buf++ = data[readIndex++];
288 if (readIndex == size)
289 {
290 readIndex = 0;
291 }
292 --count;
293 --items;
294 }
295
296 return last_count - count;
297 }
298
304 size_t data_read_pointer(T **buf)
305 {
306 size_t result = size - readIndex;
307 if (count < result)
308 {
309 result = count;
310 }
311 *buf = data + readIndex;
312 return result;
313 }
314
320 size_t data_write_pointer(T **buf)
321 {
322 size_t result = size - writeIndex;
323 if (space() < result)
324 {
325 result = space();
326 }
327 *buf = data + writeIndex;
328 return result;
329 }
330
331private:
337 DeviceBuffer(size_t size, size_t level)
339 {
340 }
341
345 {
346 }
347
349
351 T data[];
352};
353
354#endif /* _FREERTOS_DRIVERS_COMMON_DEVICE_BUFFER_HXX_ */
Helper for DeviceBuffer which allows for methods to not be inlined.
uint16_t readIndex
read index
void flush()
flush all the data out of the buffer and reset the buffer.
uint16_t level
level of space required in buffer in order to wakeup, 0 if unused
size_t advance(size_t items)
Add a number of items to the buffer by advancing the writeIndex.
size_t space()
Return the number of items for which space is available.
void signal_condition()
Signal the wakeup condition.
~DeviceBufferBase()
Destructor.
size_t pending()
Return the number of items in the queue.
uint16_t size
size in items of buffer
size_t consume(size_t items)
Remove a number of items from the buffer by advancing the readIndex.
void select_insert()
Add client to list of clients needing woken.
uint16_t writeIndex
write index
void signal_condition_from_isr()
Signal the wakeup condition from an ISR context.
DeviceBufferBase(size_t size, size_t level)
Constructor.
uint16_t count
total number of items in buffer
Implements a smart buffer specifically designed for character device drivers.
size_t get(T *buf, size_t items)
remove a number of items from the buffer.
DeviceBuffer(size_t size, size_t level)
Constructor.
static constexpr unsigned member_size()
size_t data_write_pointer(T **buf)
Get a reference to the current location in the buffer for write.
size_t put(const T *buf, size_t items)
Insert a number of items to the buffer.
T data[]
buffer data
size_t data_read_pointer(T **buf)
Get a reference to the current location in the buffer for read.
void destroy()
Destroy an existing DeviceBuffer instance.
~DeviceBuffer()
Destructor.
static DeviceBuffer * create(size_t size, size_t level=0)
Create a DeviceBuffer instance.
#define HASSERT(x)
Checks that the value of expression x is true, else terminates the current process.
Definition macros.h:138
#define DISALLOW_COPY_AND_ASSIGN(TypeName)
Removes default copy-constructor and assignment added by C++.
Definition macros.h:171
Select wakeup information.
Definition Devtab.hxx:491
static void select_wakeup_from_isr(SelectInfo *info, int *woken)
Wakeup the list of clients needing woken.
Definition Select.cxx:224
static void select_insert(SelectInfo *info)
Add client to list of clients needing woken.
Definition Select.cxx:197
static void select_wakeup(SelectInfo *info)
Wakeup the list of clients needing woken.
Definition Select.cxx:210
File information.
Definition Devtab.hxx:52