commonlib
nonblockingfifobuffer.h
Go to the documentation of this file.
1 
10 #pragma once
11 
12 #include "memory.h"
13 #include <atomic>
14 #include <vector>
15 
16 BEGIN_NAMESPACE_MEMORY
17 
18 template <typename T>
20 {
21  static_assert(std::is_trivially_copyable_v<T>, "Only trivially copyable types are supported in direct array source buffer.");
22 
23 public:
24 
25  using BufferIndex = std::size_t;
26 
27 
29  {
30  setCapacity(0);
31  }
32 
33  explicit NonblockingFifoBuffer(const std::size_t aCapacity)
34  {
35  setCapacity(aCapacity);
36  }
37 
39  {
40  }
41 
44  NonblockingFifoBuffer& operator=(const NonblockingFifoBuffer&) = delete;
45  NonblockingFifoBuffer& operator=(const NonblockingFifoBuffer&&) = delete;
46 
47  void setCapacity(const std::size_t aCapacity)
48  {
49  writeIndex = 0;
50  readIndex = 0;
51  buffer = std::vector<T>(aCapacity);
52  }
53 
54  std::size_t getCapacity() const
55  {
56  return buffer.size();
57  }
58 
59  std::size_t getSize() const
60  {
61  const BufferIndex cachedWriteIndex = writeIndex;
62  if (readIndex <= cachedWriteIndex)
63  return cachedWriteIndex - readIndex;
64  else
65  return (buffer.size() - readIndex) + cachedWriteIndex;
66  }
67 
68  BufferIndex getIndex() const
69  {
70  return writeIndex;
71  }
72 
73  size_t writeSamples(T* source, std::size_t size)
74  {
75  if (size > buffer.size())
76  {
77  throw "Buffer size exceeded";
78  }
79  size_t totalSizeWritten = size;
80 
81  if (writeIndex + size > buffer.size())
82  {
83  std::size_t sizeUntilFullCapacity = buffer.size() - writeIndex;
84  writeSamples(source, sizeUntilFullCapacity);
85  size -= sizeUntilFullCapacity;
86  source += sizeUntilFullCapacity;
87  }
88 
89  std::memcpy(&buffer.data()[writeIndex], source, size * sizeof(T));
90 
91  {
92  BufferIndex newWriteIndex = writeIndex + size;
93  if (newWriteIndex >= buffer.size())
94  newWriteIndex -= buffer.size();
95  writeIndex = newWriteIndex;
96  }
97  return totalSizeWritten;
98  }
99 
100  size_t readSamples(T* destination, size_t count)
101  {
102  count = std::min(count, getSize());
103  std::size_t readCapacity = 0;
104  if (readIndex + count > buffer.size())
105  {
106  readCapacity = buffer.size() - readIndex;
107  std::memcpy(destination, &buffer.data()[readIndex], readCapacity * sizeof(T));
108  readIndex = 0;
109  destination += readCapacity;
110  count -= readCapacity;
111  }
112  std::memcpy(destination, &buffer.data()[readIndex], count * sizeof(T));
113  readIndex += count;
114  return count + readCapacity;
115  }
116 
117 private:
118  std::vector<T> buffer;
119  BufferIndex readIndex{};
120  std::atomic<BufferIndex> writeIndex{};
121 };
122 
123 END_NAMESPACE_MEMORY
Definition: nonblockingfifobuffer.h:19