Yet Another Synthesizer Engine
 
Loading...
Searching...
No Matches
ring_buffer.hh
1
8#include <iostream>
9#include <memory>
10
11namespace yase {
12
14
18
19 template<typename DataType> class RingBuffer {
20 public:
21
22 RingBuffer(int capacity) :
23 m_capacity(capacity),
24 m_freeItems(capacity),
25 m_readIndex(0),
26 m_writeIndex(0) {
27
28 static_assert(ATOMIC_INT_LOCK_FREE == 2);
29 m_spBuffer = std::make_unique<DataType[]>(m_capacity);
30 memset(m_spBuffer.get(), 0, sizeof(DataType) * m_capacity);
31
32 }
33
34 int getReadableItemCount() const {
35 return m_capacity - m_freeItems.load();
36 }
37
38 int getWriteableItemCount() const {
39 return m_freeItems.load();
40 }
41
42 int read(DataType * pData, int max) {
43
44 int readableItemCount = getReadableItemCount();
45 if (readableItemCount == 0)
46 return 0;
47
48 int totalItemsToRead = std::min(readableItemCount, max);
49 int itemsLeftToRead = totalItemsToRead;
50
51 if (m_readIndex + itemsLeftToRead >= m_capacity) {
52 int itemsAvailableUntilEnd = m_capacity - m_readIndex;
53 memcpy(pData, m_spBuffer.get() + m_readIndex, itemsAvailableUntilEnd * sizeof(DataType));
54 m_readIndex = 0;
55 itemsLeftToRead -= itemsAvailableUntilEnd;
56 pData += itemsAvailableUntilEnd;
57 }
58
59 if (itemsLeftToRead > 0) {
60 memcpy(pData, m_spBuffer.get() + m_readIndex, itemsLeftToRead * sizeof(DataType));
61 m_readIndex += itemsLeftToRead;
62 itemsLeftToRead = 0;
63 }
64
65 m_freeItems += totalItemsToRead; // this is atomic
66 return totalItemsToRead;
67 }
68
69 int write(DataType * pData, int numItems) {
70
71 int writeableItemCount = getWriteableItemCount();
72 if (writeableItemCount == 0)
73 return 0;
74
75 int totalItemsToWrite = std::min(writeableItemCount, numItems);
76 int itemsLeftToWrite = totalItemsToWrite;
77
78 if ((m_writeIndex + itemsLeftToWrite) >= m_capacity) {
79 int itemsAvailableUntilEnd = m_capacity - m_writeIndex;
80 memcpy(m_spBuffer.get() + m_writeIndex, pData, itemsAvailableUntilEnd * sizeof(DataType));
81 m_writeIndex = 0;
82 itemsLeftToWrite -= itemsAvailableUntilEnd;
83 pData += itemsAvailableUntilEnd;
84 }
85
86 if (itemsLeftToWrite > 0) {
87 memcpy(m_spBuffer.get() + m_writeIndex, pData, itemsLeftToWrite * sizeof(DataType));
88 m_writeIndex += itemsLeftToWrite;
89 itemsLeftToWrite = 0;
90 }
91
92 m_freeItems -= totalItemsToWrite; // this is atomic
93 return totalItemsToWrite;
94
95 }
96 private:
97
98 std::unique_ptr<DataType[]> m_spBuffer; // The data.
99 int m_writeIndex; // Where the producer is writing to next.
100 int m_readIndex; // Where the consumer is reading from next.
101
102 const int m_capacity; // Total number of frames managed by the ring buffer.
103 std::atomic<int> m_freeItems; // Number of frames that are available to be written into.
104
105 };
106
107}
A Ring Buffer for multi-threaded communications.
Definition ring_buffer.hh:19
Definition additive_saw.cc:24