commonlib
direct_array_buffer.h
Go to the documentation of this file.
1 
12 #pragma once
13 
14 #include "buffer.h"
15 #include <cstring>
16 #include <algorithm>
17 
18 BEGIN_NAMESPACE_MEMORY
19 
23 template <typename T, typename Locking = UseLock>
25 {
26  static_assert(std::is_trivially_copyable_v<T>, "Only trivially copyable types are supported in direct array source buffer.");
27 
28 public:
33  virtual T* getData() const = 0;
34 
39  virtual size_t getCapacity() const = 0;
40 
45  virtual size_t getReadPos() = 0;
46 
54  size_t readSamples(T* samples, size_t samplesCount, bool incrementPosition = true) override
55  {
56  return readSamplesAt(samples, samplesCount, incrementPosition, 0);
57  }
58 
67  virtual size_t readSamplesAt(T* samples, size_t samplesCount, bool incrementPosition = true, size_t readOffset = 0)
68  {
70 
71  size_t readPos{this->getReadPos()};
72 
73  if (readOffset > 0)
74  {
75  readPos = (readPos + readOffset) % this->getCapacity();
76  readOffset = std::min<size_t>(this->getSize(), readOffset);
77  }
78 
79  samplesCount = std::min<size_t>(samplesCount, this->getSize() - readOffset);
80 
81  if (samplesCount > 0)
82  {
83  if (readPos + samplesCount < this->getCapacity())
84  {
85  read(samples, samplesCount, readPos);
86  }
87  else
88  {
89  size_t firstSamplesCount = getCapacity() - readPos;
90  read(samples, firstSamplesCount, readPos);
91  size_t secondSamplesCount = samplesCount - firstSamplesCount;
92  read(&samples[firstSamplesCount], secondSamplesCount, 0);
93  }
94  if (incrementPosition)
95  this->incrementReadPosition(samplesCount);
96  }
97 
98  return samplesCount;
99  }
100 
101 protected:
109  virtual size_t read(T* samples, size_t samplesCount, size_t pos)
110  {
111  std::memcpy(samples, &getData()[pos], samplesCount * sizeof(T));
112  return samplesCount;
113  }
114 
121  virtual size_t read(T* samples, size_t samplesCount)
122  {
123  return read(samples, samplesCount, getReadPos());
124  }
125 };
126 
130 template <typename T>
132 {
133  static_assert(std::is_trivially_copyable_v<T>, "Only trivially copyable types are supported in direct array target buffer.");
134 
135 public:
140  virtual T* getData() const = 0;
141 
146  virtual size_t getCapacity() const = 0;
147 
152  virtual size_t getWritePos() = 0;
153 
161  size_t writeSamples(const T* samples, size_t samplesCount, bool incrementPosition = true) override
162  {
163  std::lock_guard<std::recursive_mutex> guard(this->getLock());
164 
165  samplesCount = std::min<size_t>(samplesCount, this->getRemainingSize());
166 
167  if (samplesCount > 0)
168  {
169  if (getWritePos() + samplesCount <= getCapacity())
170  {
171  write(samples, samplesCount);
172  }
173  else
174  {
175  size_t firstSamplesCount = getCapacity() - getWritePos();
176  write(samples, firstSamplesCount);
177  size_t secondSamplesCount = samplesCount - firstSamplesCount;
178  write(&samples[firstSamplesCount], secondSamplesCount, 0);
179  }
180 
181  if (incrementPosition)
182  this->incrementWritePosition(samplesCount);
183  }
184 
185  return samplesCount;
186  }
187 
188 protected:
196  virtual size_t write(const T* samples, size_t samplesCount, size_t pos)
197  {
198  std::memcpy(&getData()[pos], samples, samplesCount * sizeof(T));
199  return samplesCount;
200  }
201 
208  virtual size_t write(const T* samples, size_t samplesCount)
209  {
210  return write(samples, samplesCount, getWritePos());
211  }
212 };
213 
214 /*operations*/
215 
216 template <typename T>
217 static void operator<<(IDirectArrayTargetBuffer<T>& target, ISourceBuffer<T>& source)
218 {
219  transferBuffer(source, target);
220 }
221 
222 template <typename T>
223 static void operator>>(ISourceBuffer<T>& source, IDirectArrayTargetBuffer<T>& target)
224 {
225  transferBuffer(source, target);
226 }
227 
236 template <typename T, typename Locking = UseLock>
239  bool incrementPosition = true,
240  size_t samplesCount = (std::numeric_limits<size_t>::max)())
241 {
244 
245  samplesCount = std::min<size_t>(std::min<size_t>(samplesCount, source.getSize()), target.getRemainingSize());
246 
247  if (samplesCount > 0)
248  {
249  if (target.getWritePos() + samplesCount <= target.getCapacity())
250  {
251  source.readSamples(&target.getData()[target.getWritePos()], samplesCount, incrementPosition);
252  }
253  else
254  {
255  size_t firstSamplesCount = target.getCapacity() - target.getWritePos();
256  source.readSamples(&target.getData()[target.getWritePos()], firstSamplesCount, incrementPosition);
257  size_t secondSamplesCount = samplesCount - firstSamplesCount;
258  source.readSamples(target.getData(), secondSamplesCount, incrementPosition);
259  }
260 
261  if (incrementPosition)
262  target.incrementWritePosition(samplesCount);
263  }
264 
265  return samplesCount;
266 }
267 
268 template <typename T>
269 static void operator<<(ISourceBuffer<T>& target, IDirectArrayTargetBuffer<T>& source)
270 {
271  transferBuffer(source, target);
272 }
273 
274 template <typename T>
275 static void operator>>(IDirectArrayTargetBuffer<T>& source, ISourceBuffer<T>& target)
276 {
277  transferBuffer(source, target);
278 }
279 
289 template <typename T>
291  ITargetBuffer<T>& target,
292  bool incrementPosition = true,
293  size_t samplesCount = (std::numeric_limits<size_t>::max)(),
294  bool earlyReleaseSourceLock = false)
295 {
296  std::unique_lock<std::recursive_mutex> guardS(source.getLock());
297  size_t sourceSize = source.getSize();
298  size_t sourceCapacity = source.getCapacity();
299  size_t sourceReadPos = source.getReadPos();
300 
301  if (earlyReleaseSourceLock)
302  guardS.unlock();
303 
304  std::lock_guard<std::recursive_mutex> guardT(target.getLock());
305 
306  samplesCount = std::min<size_t>(std::min<size_t>(samplesCount, sourceSize), target.getRemainingSize());
307 
308  if (samplesCount > 0)
309  {
310  if (sourceReadPos + samplesCount <= sourceCapacity)
311  {
312  target.writeSamples(&source.getData()[sourceReadPos], samplesCount, incrementPosition);
313  }
314  else
315  {
316  size_t firstSamplesCount = sourceCapacity - sourceReadPos;
317  target.writeSamples(&source.getData()[sourceReadPos], firstSamplesCount, incrementPosition);
318  size_t secondSamplesCount = samplesCount - firstSamplesCount;
319  target.writeSamples(source.getData(), secondSamplesCount, incrementPosition);
320  }
321 
322  if (incrementPosition)
323  source.incrementReadPosition(samplesCount);
324  }
325 
326  return samplesCount;
327 }
328 
329 template <typename T>
330 static void operator<<(IDirectArraySourceBuffer<T>& target, IDirectArrayTargetBuffer<T>& source)
331 {
332  transferBuffer(source, target);
333 }
334 
335 template <typename T>
336 static void operator>>(IDirectArrayTargetBuffer<T>& source, IDirectArraySourceBuffer<T>& target)
337 {
338  transferBuffer(source, target);
339 }
340 
349 template <typename T>
352  bool incrementPosition = true,
353  size_t samplesCount = (std::numeric_limits<size_t>::max)())
354 {
355  return transferBuffer(source, static_cast<ITargetBuffer<T>&>(target), incrementPosition, samplesCount);
356 }
357 
358 END_NAMESPACE_MEMORY
virtual void incrementReadPosition(size_t pos)=0
Function increments read position for N samples.
virtual std::recursive_mutex & getLock()=0
Function return locking object.
virtual size_t read(T *samples, size_t samplesCount, size_t pos)
Implements read from buffer.
Definition: direct_array_buffer.h:109
Basic source buffer interface.
Definition: buffer.h:25
Interface to array-backed source buffers.
Definition: direct_array_buffer.h:24
virtual size_t write(const T *samples, size_t samplesCount, size_t pos)
Implements write into buffer.
Definition: direct_array_buffer.h:196
virtual size_t getCapacity() const =0
Function returns buffer capacity in samples.
virtual size_t read(T *samples, size_t samplesCount)
Function read from buffer from current location.
Definition: direct_array_buffer.h:121
size_t transferBuffer(ISourceBuffer< T > &source, IDirectArrayTargetBuffer< T > &target, bool incrementPosition=true, size_t samplesCount=(std::numeric_limits< size_t >::max)())
Transferring data from one buffer to another without intermediate buffer.
Definition: direct_array_buffer.h:237
Definition: lock_guard.h:29
virtual size_t getRemainingSize()=0
Function returns remaining size in samples.
virtual size_t getSize()=0
Function returns current buffer size in samples.
virtual void incrementWritePosition(size_t pos)=0
Function increments write position for N samples.
virtual size_t getReadPos()=0
Function returns current read position.
virtual size_t getCapacity() const =0
Function returns buffer capacity in samples.
Basic source and target buffer interface and data transferring operation.
size_t writeSamples(const T *samples, size_t samplesCount, bool incrementPosition=true) override
Function pushes the samples into buffer.
Definition: direct_array_buffer.h:161
Interface to array-backed target buffers.
Definition: direct_array_buffer.h:131
virtual size_t writeSamples(const T *samples, size_t samplesCount, bool incrementPosition=true)=0
Function pushes the samples into buffer.
virtual std::recursive_mutex & getLock()=0
Function return locking object.
virtual size_t getWritePos()=0
Function returns current write position.
virtual size_t readSamples(T *samples, size_t samplesCount, bool incrementPosition=true)=0
Function reads the samples from buffer.
virtual size_t write(const T *samples, size_t samplesCount)
Implements write into buffer to current location.
Definition: direct_array_buffer.h:208
virtual size_t readSamplesAt(T *samples, size_t samplesCount, bool incrementPosition=true, size_t readOffset=0)
Function reads the samples from buffer.
Definition: direct_array_buffer.h:67
Basic target buffer interface.
Definition: buffer.h:63
size_t readSamples(T *samples, size_t samplesCount, bool incrementPosition=true) override
Function reads the samples from buffer.
Definition: direct_array_buffer.h:54
virtual T * getData() const =0
Function returns pointer to the internal buffer.
virtual T * getData() const =0
Function returns pointer to the internal buffer.