28 jassert (bufferSize > 0);
38 auto vs = validStart.
get();
39 auto ve = validEnd.
get();
40 return ve >= vs ? (ve - vs) : (bufferSize - (vs - ve));
51 jassert (newSize > 0);
58 int& startIndex2,
int& blockSize2)
const noexcept
60 auto vs = validStart.
get();
61 auto ve = validEnd.
get();
63 auto freeSpace = ve >= vs ? (bufferSize - (ve - vs)) : (vs - ve);
64 numToWrite = jmin (numToWrite, freeSpace - 1);
77 blockSize1 = jmin (bufferSize - ve, numToWrite);
78 numToWrite -= blockSize1;
79 blockSize2 = numToWrite <= 0 ? 0 : jmin (numToWrite, vs);
85 jassert (numWritten >= 0 && numWritten < bufferSize);
87 auto newEnd = validEnd.
get() + numWritten;
89 if (newEnd >= bufferSize)
96 int& startIndex2,
int& blockSize2)
const noexcept
98 auto vs = validStart.
get();
99 auto ve = validEnd.
get();
101 auto numReady = ve >= vs ? (ve - vs) : (bufferSize - (vs - ve));
102 numWanted = jmin (numWanted, numReady);
115 blockSize1 = jmin (bufferSize - vs, numWanted);
116 numWanted -= blockSize1;
117 blockSize2 = numWanted <= 0 ? 0 : jmin (numWanted, ve);
123 jassert (numRead >= 0 && numRead <= bufferSize);
125 auto newStart = validStart.
get() + numRead;
127 if (newStart >= bufferSize)
128 newStart -= bufferSize;
130 validStart = newStart;
134 template <AbstractFifo::ReadOrWrite mode>
136 : startIndex1 (other.startIndex1),
137 blockSize1 (other.blockSize1),
138 startIndex2 (other.startIndex2),
139 blockSize2 (other.blockSize2)
144 template <AbstractFifo::ReadOrWrite mode>
152 template <AbstractFifo::ReadOrWrite mode>
155 std::swap (other.fifo, fifo);
156 std::swap (other.startIndex1, startIndex1);
157 std::swap (other.blockSize1, blockSize1);
158 std::swap (other.startIndex2, startIndex2);
159 std::swap (other.blockSize2, blockSize2);
173 class AbstractFifoTests :
public UnitTest 177 :
UnitTest (
"Abstract Fifo", UnitTestCategories::containers)
180 struct WriteThread :
public Thread 183 :
Thread (
"fifo writer"), fifo (f), buffer (b), random (rng)
197 while (! threadShouldExit())
199 int num = random.nextInt (2000) + 1;
201 auto writer = fifo.write (num);
203 jassert (writer.blockSize1 >= 0 && writer.blockSize2 >= 0);
204 jassert (writer.blockSize1 == 0
205 || (writer.startIndex1 >= 0 && writer.startIndex1 < fifo.getTotalSize()));
206 jassert (writer.blockSize2 == 0
207 || (writer.startIndex2 >= 0 && writer.startIndex2 < fifo.getTotalSize()));
209 writer.forEach ([
this, &n] (
int index) { this->buffer[index] = n++; });
218 void runTest()
override 220 beginTest (
"AbstractFifo");
225 WriteThread writer (fifo, buffer, getRandom());
231 for (
int count = 100000; --count >= 0;)
233 int num = r.
nextInt (6000) + 1;
235 auto reader = fifo.
read (num);
237 if (! (reader.blockSize1 >= 0 && reader.blockSize2 >= 0)
238 && (reader.blockSize1 == 0
239 || (reader.startIndex1 >= 0 && reader.startIndex1 < fifo.
getTotalSize()))
240 && (reader.blockSize2 == 0
241 || (reader.startIndex2 >= 0 && reader.startIndex2 < fifo.
getTotalSize())))
243 expect (
false,
"prepareToRead returned -ve values");
249 reader.forEach ([&failed, &buffer, &n] (
int index)
251 failed = (buffer[index] != n++) || failed;
256 expect (
false,
"read values were incorrect");
263 static AbstractFifoTests fifoUnitTests;
AbstractFifo(int capacity) noexcept
Creates a FIFO to manage a buffer with the specified capacity.
Class for a scoped reader/writer.
void finishedRead(int numRead) noexcept
Called after reading from the FIFO, to indicate that this many items have now been consumed...
ScopedReadWrite()=default
Construct an unassigned reader/writer.
void combineSeed(int64 seedValue) noexcept
Merges this object's seed with another value.
int nextInt() noexcept
Returns the next random 32 bit integer.
int getTotalSize() const noexcept
Returns the total size of the buffer being managed.
void reset() noexcept
Clears the buffer positions, so that it appears empty.
This is a base class for classes that perform a unit test.
void setTotalSize(int newSize) noexcept
Changes the buffer's total size.
int getNumReady() const noexcept
Returns the number of items that can currently be read from the buffer.
void prepareToWrite(int numToWrite, int &startIndex1, int &blockSize1, int &startIndex2, int &blockSize2) const noexcept
Returns the location within the buffer at which an incoming block of data should be written...
Encapsulates the logic required to implement a lock-free FIFO.
ScopedWrite write(int numToWrite) noexcept
Replaces prepareToWrite/finishedWrite with a single function.
void finishedWrite(int numWritten) noexcept
Called after writing from the FIFO, to indicate that this many items have been added.
Type get() const noexcept
Atomically reads and returns the current value.
void prepareToRead(int numWanted, int &startIndex1, int &blockSize1, int &startIndex2, int &blockSize2) const noexcept
Returns the location within the buffer from which the next block of data should be read...
A random number generator.
ScopedRead read(int numToRead) noexcept
Replaces prepareToRead/finishedRead with a single function.
int getFreeSpace() const noexcept
Returns the number of items that can currently be added to the buffer without it overflowing.
~AbstractFifo()
Destructor.