-
Notifications
You must be signed in to change notification settings - Fork 3
/
RingBuffer.h
143 lines (117 loc) · 3.82 KB
/
RingBuffer.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
RingBuffer.h
Copyright (c) 2020-2022 Timo Lappalainen
The MIT License
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Simple tRingBuffer and tPriorityRingBuffer template classes.
With tRingBuffer one can save simple data structures to ring buffer.
Note that you have to take care of data locking from other threads or interrupts for copy time.
E.g.
struct tCANData {
uint32_t id;
uint8_t len;
uint8_t data[8];
};
tPriorityRingBuffer<tCANData> CANMessages(100);
...
void SendMessage() {
tCANData msgOut;
msgOut.id=1;
msgOut.len=1;
msgOut.data[0]=1;
lockData();
CANMessages.add(msgOut);
releaseData();
}
As an alternative if you want to avoid data copying twice, you can request reference to next
data to be saved and copy data directly to it.
void SendMessage() {
tCANData *msgOut;
lockData();
if ( (msgOut=CANMessages)!=0 ) {
msgOut->id=1;
msgOut->len=1;
msgOut->data[0]=1;
}
releaseData();
}
tPriorityRingBuffer is similar as tRingBuffer, but it extends functionality with item priority. When you add
items to buffer, you can give them priority and when you read them, highest priority item will be read out
first.
*/
#ifndef _RING_BUFFER_H_
#define _RING_BUFFER_H_
#include <cstdint>
template <typename T> class tRingBuffer {
protected:
T *buffer;
uint16_t head;
uint16_t tail;
uint16_t size;
public:
tRingBuffer(uint16_t _size);
virtual ~tRingBuffer();
uint16_t getSize() const { return size; }
bool isEmpty() const;
void clear();
uint16_t count();
// Get pointer to next add item if available.
T *getAddRef();
bool add(const T &val);
// Get pointer to next read item if available.
const T *getReadRef();
bool read(T &val);
};
template <typename T> class tPriorityRingBuffer {
protected:
#define INVALID_RING_REF (uint16_t)(-1)
#define INVALID_PRIORITY_REF (uint8_t)(-1)
struct tValueSlot {
T Value;
uint16_t next;
uint8_t priority;
};
struct tPriorityRef {
uint16_t next;
uint16_t last;
tPriorityRef() : next(INVALID_RING_REF), last(INVALID_RING_REF) {;}
void clear() { next=INVALID_RING_REF; last=INVALID_RING_REF; }
};
protected:
uint16_t head;
uint16_t tail;
uint16_t size;
uint8_t maxPriorities;
tValueSlot *buffer;
tPriorityRef *priorityReferencies;
public:
tPriorityRingBuffer(uint16_t _size, uint8_t _maxPriorities=1);
virtual ~tPriorityRingBuffer();
uint16_t getSize() const { return size; }
bool isEmpty(uint8_t _priority=0xff) const;
void clear();
void clean();
uint16_t count();
bool add(const T &val, uint8_t _priority=0);
bool read(T &val);
T *getAddRef(uint8_t _priority=0);
const T *getReadRef(uint8_t _priority);
// Get reference to highest available.
const T *getReadRef(uint8_t *_priority=0);
};
#include "RingBuffer.tpp"
#endif