Skip to content

Commit 3789df4

Browse files
committed
CircularBuffer
1 parent 2d3f1a3 commit 3789df4

File tree

8 files changed

+307
-23
lines changed

8 files changed

+307
-23
lines changed

Common/Cpp/Containers/AlignedVector.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,15 @@ class AlignedVector{
1818
~AlignedVector();
1919
AlignedVector(AlignedVector&& x) noexcept;
2020
void operator=(AlignedVector&& x) noexcept;
21-
AlignedVector(const AlignedVector&);
22-
void operator=(const AlignedVector&);
21+
AlignedVector(const AlignedVector& x);
22+
void operator=(const AlignedVector& x);
2323

2424
public:
2525
AlignedVector();
2626
AlignedVector(size_t items);
2727

28+
void clear() noexcept;
29+
2830
public:
2931
size_t empty() const{ return m_size == 0; }
3032
size_t size() const{ return m_size; }
@@ -42,8 +44,6 @@ class AlignedVector{
4244
void emplace_back(Args&&... args);
4345
void pop_back();
4446

45-
void clear();
46-
4747
const Object* begin() const;
4848
Object* begin();
4949
const Object* end() const;

Common/Cpp/Containers/AlignedVector.tpp

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,10 @@ AlignedVector<Object>::AlignedVector(const AlignedVector& x)
5959
break;
6060
}
6161
}
62-
m_ptr = (Object*)aligned_malloc(m_capacity * sizeof(Object), 64);
62+
m_ptr = (Object*)aligned_malloc(
63+
m_capacity * sizeof(Object),
64+
std::max<size_t>(alignof(Object), 64)
65+
);
6366
if (m_ptr == nullptr){
6467
throw std::bad_alloc();
6568
}
@@ -119,6 +122,17 @@ AlignedVector<Object>::AlignedVector(size_t items){
119122
}
120123
}
121124

125+
template <typename Object>
126+
void AlignedVector<Object>::clear() noexcept{
127+
if constexpr (std::is_trivially_constructible<Object>::value){
128+
m_size = 0;
129+
}else{
130+
while (m_size > 0){
131+
pop_back();
132+
}
133+
}
134+
}
135+
122136
template <typename Object>
123137
template <class... Args>
124138
void AlignedVector<Object>::emplace_back(Args&&... args){
@@ -132,16 +146,6 @@ template <typename Object>
132146
void AlignedVector<Object>::pop_back(){
133147
m_ptr[--m_size].~Object();
134148
}
135-
template <typename Object>
136-
void AlignedVector<Object>::clear(){
137-
if constexpr (std::is_trivially_constructible<Object>::value){
138-
m_size = 0;
139-
}else{
140-
while (m_size > 0){
141-
pop_back();
142-
}
143-
}
144-
}
145149

146150
template <typename Object>
147151
PA_NO_INLINE void AlignedVector<Object>::expand(){
Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
/* Circular Buffer
2+
*
3+
* From: https://github.com/PokemonAutomation/Arduino-Source
4+
*
5+
*/
6+
7+
#ifndef PokemonAutomation_CircularBuffer_H
8+
#define PokemonAutomation_CircularBuffer_H
9+
10+
#include <new>
11+
#include <utility>
12+
#include "Common/Cpp/Exceptions.h"
13+
#include "Common/Cpp/Containers/AlignedMalloc.h"
14+
15+
namespace PokemonAutomation{
16+
17+
18+
19+
template <typename Object>
20+
class CircularBuffer{
21+
public:
22+
~CircularBuffer();
23+
CircularBuffer(CircularBuffer&& x) noexcept;
24+
void operator=(CircularBuffer&& x) noexcept;
25+
CircularBuffer(const CircularBuffer& x);
26+
void operator=(const CircularBuffer& x);
27+
28+
public:
29+
CircularBuffer();
30+
CircularBuffer(size_t capacity);
31+
32+
void clear() noexcept;
33+
34+
size_t empty() const{ return m_front == m_back; }
35+
size_t size() const{ return m_back - m_front; }
36+
37+
const Object& front() const;
38+
Object& front();
39+
const Object& operator[](size_t index) const;
40+
Object& operator[](size_t index);
41+
42+
43+
template <class... Args>
44+
Object& push_back(Args&&... args);
45+
void pop_front();
46+
47+
private:
48+
size_t m_capacity;
49+
size_t m_front;
50+
size_t m_back;
51+
Object* m_ptr;
52+
};
53+
54+
55+
56+
template <typename Object>
57+
CircularBuffer<Object>::~CircularBuffer(){
58+
clear();
59+
aligned_free(m_ptr);
60+
}
61+
template <typename Object>
62+
CircularBuffer<Object>::CircularBuffer(CircularBuffer&& x) noexcept
63+
: m_capacity(x.m_capacity)
64+
, m_front(x.m_front)
65+
, m_back(x.m_back)
66+
, m_ptr(x.m_ptr)
67+
{
68+
x.m_capacity = 0;
69+
x.m_front = 0;
70+
x.m_back = 0;
71+
x.m_ptr = nullptr;
72+
}
73+
template <typename Object>
74+
void CircularBuffer<Object>::operator=(CircularBuffer&& x) noexcept{
75+
if (this == &x){
76+
return;
77+
}
78+
clear();
79+
aligned_free(m_ptr);
80+
m_capacity = x.m_capacity;
81+
m_front = x.m_front;
82+
m_back = x.m_back;
83+
m_ptr = x.m_ptr;
84+
x.m_capacity = 0;
85+
x.m_front = 0;
86+
x.m_back = 0;
87+
x.m_ptr = nullptr;
88+
}
89+
template <typename Object>
90+
CircularBuffer<Object>::CircularBuffer(const CircularBuffer& x)
91+
: CircularBuffer(x.m_capacity)
92+
{
93+
size_t size = x.size();
94+
for (size_t c = 0; c < size; c++){
95+
push_back(x[c]);
96+
}
97+
}
98+
template <typename Object>
99+
void CircularBuffer<Object>::operator=(const CircularBuffer& x){
100+
if (this == &x){
101+
return;
102+
}
103+
CircularBuffer tmp(x);
104+
*this = std::move(tmp);
105+
}
106+
107+
template <typename Object>
108+
CircularBuffer<Object>::CircularBuffer()
109+
: m_capacity(0)
110+
, m_front(0)
111+
, m_back(0)
112+
, m_ptr(nullptr)
113+
{}
114+
template <typename Object>
115+
CircularBuffer<Object>::CircularBuffer(size_t capacity)
116+
: m_capacity(capacity)
117+
, m_front(0)
118+
, m_back(0)
119+
, m_ptr(nullptr)
120+
{
121+
if (capacity == 0){
122+
return;
123+
}
124+
m_ptr = (Object*)aligned_malloc(capacity * sizeof(Object), alignof(Object));
125+
if (m_ptr == nullptr){
126+
throw std::bad_alloc();
127+
}
128+
}
129+
130+
template <typename Object>
131+
void CircularBuffer<Object>::clear() noexcept{
132+
while (m_back > m_front){
133+
pop_front();
134+
}
135+
}
136+
137+
138+
template <typename Object>
139+
const Object& CircularBuffer<Object>::front() const{
140+
return m_ptr[m_front];
141+
}
142+
template <typename Object>
143+
Object& CircularBuffer<Object>::front(){
144+
return m_ptr[m_front];
145+
}
146+
template <typename Object>
147+
const Object& CircularBuffer<Object>::operator[](size_t index) const{
148+
index += m_front;
149+
if (index >= m_capacity){
150+
index -= m_capacity;
151+
}
152+
return m_ptr[index];
153+
}
154+
template <typename Object>
155+
Object& CircularBuffer<Object>::operator[](size_t index){
156+
index += m_front;
157+
if (index >= m_capacity){
158+
index -= m_capacity;
159+
}
160+
return m_ptr[index];
161+
}
162+
163+
template <typename Object>
164+
template <class... Args>
165+
Object& CircularBuffer<Object>::push_back(Args&&... args){
166+
if (m_back - m_front >= m_capacity){
167+
throw InternalProgramError(nullptr, PA_CURRENT_FUNCTION, "CircularBuffer: Attempted to push while full.");
168+
}
169+
size_t back = m_back;
170+
if (back >= m_capacity){
171+
back -= m_capacity;
172+
}
173+
new (m_ptr + back) Object(std::forward<Args>(args)...);
174+
m_back++;
175+
return m_ptr[back];
176+
}
177+
178+
template <typename Object>
179+
void CircularBuffer<Object>::pop_front(){
180+
if (m_front == m_back){
181+
throw InternalProgramError(nullptr, PA_CURRENT_FUNCTION, "CircularBuffer: Attempted to pop while empty.");
182+
}
183+
size_t front = m_front;
184+
m_ptr[front].~Object();
185+
front++;
186+
size_t diff = front >= m_capacity ? m_capacity : 0;
187+
m_front = front - diff;
188+
m_back -= diff;
189+
}
190+
191+
192+
193+
194+
195+
196+
197+
}
198+
#endif

SerialPrograms/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,7 @@ file(GLOB MAIN_SOURCES
8787
../Common/Cpp/Containers/AlignedVector.h
8888
../Common/Cpp/Containers/AlignedVector.tpp
8989
../Common/Cpp/Containers/BoxSet.h
90+
../Common/Cpp/Containers/CircularBuffer.h
9091
../Common/Cpp/Containers/DllSafeString.h
9192
../Common/Cpp/Containers/FixedLimitVector.h
9293
../Common/Cpp/Containers/FixedLimitVector.tpp

SerialPrograms/SerialPrograms.pro

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,6 +1157,7 @@ HEADERS += \
11571157
../Common/Cpp/Containers/AlignedVector.h \
11581158
../Common/Cpp/Containers/AlignedVector.tpp \
11591159
../Common/Cpp/Containers/BoxSet.h \
1160+
../Common/Cpp/Containers/CircularBuffer.h \
11601161
../Common/Cpp/Containers/DllSafeString.h \
11611162
../Common/Cpp/Containers/FixedLimitVector.h \
11621163
../Common/Cpp/Containers/FixedLimitVector.tpp \

SerialPrograms/Source/NintendoSwitch/Controllers/SysbotBase/SysbotBase_ProController.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ ProController_SysbotBase::ProController_SysbotBase(
3030
, m_connection(connection)
3131
, m_stopping(false)
3232
, m_replace_on_next(false)
33+
, m_command_queue(QUEUE_SIZE)
3334
, m_is_active(false)
3435
{
3536
if (!connection.is_ready()){
@@ -170,7 +171,7 @@ void ProController_SysbotBase::push_state(const Cancellable* cancellable, WallDu
170171
m_cv.notify_all();
171172
}
172173

173-
Command& command = m_command_queue.emplace_back();
174+
Command& command = m_command_queue.push_back();
174175

175176
command.state.buttons = buttons;
176177
command.state.dpad = dpad;

SerialPrograms/Source/NintendoSwitch/Controllers/SysbotBase/SysbotBase_ProController.h

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
#ifndef PokemonAutomation_NintendoSwitch_ProController_SysbotBase_H
99
#define PokemonAutomation_NintendoSwitch_ProController_SysbotBase_H
1010

11-
#include <mutex>
1211
#include <condition_variable>
12+
#include "Common/Cpp/Containers/CircularBuffer.h"
1313
#include "NintendoSwitch/Controllers/NintendoSwitch_VirtualControllerState.h"
1414
#include "NintendoSwitch/Controllers/NintendoSwitch_ProControllerWithScheduler.h"
1515
#include "SysbotBase_Connection.h"
@@ -23,7 +23,7 @@ class ProController_SysbotBase : public ProControllerWithScheduler{
2323
public:
2424
using ContextType = ProControllerContext;
2525

26-
static constexpr size_t QUEUE_SIZE = 32;
26+
static constexpr size_t QUEUE_SIZE = 4;
2727
static constexpr std::chrono::microseconds EARLY_WAKE_SPIN = std::chrono::microseconds(2000);
2828

2929

@@ -81,11 +81,10 @@ class ProController_SysbotBase : public ProControllerWithScheduler{
8181
SwitchControllerState state;
8282
Milliseconds duration;
8383
};
84-
std::deque<Command> m_command_queue;
84+
CircularBuffer<Command> m_command_queue;
8585
WallClock m_queue_start_time;
8686
bool m_is_active;
8787

88-
// std::mutex m_lock;
8988
std::condition_variable m_cv;
9089
std::thread m_dispatch_thread;
9190
};

0 commit comments

Comments
 (0)