The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

234 lines
6.7KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library - "Jules' Utility Class Extensions"
  4. Copyright 2004-11 by Raw Material Software Ltd.
  5. ------------------------------------------------------------------------------
  6. JUCE can be redistributed and/or modified under the terms of the GNU General
  7. Public License (Version 2), as published by the Free Software Foundation.
  8. A copy of the license is included in the JUCE distribution, or can be found
  9. online at www.gnu.org/licenses.
  10. JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
  11. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  12. A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  13. ------------------------------------------------------------------------------
  14. To release a closed-source product which uses JUCE, commercial licenses are
  15. available: visit www.rawmaterialsoftware.com/juce for more information.
  16. ==============================================================================
  17. */
  18. AbstractFifo::AbstractFifo (const int capacity) noexcept
  19. : bufferSize (capacity)
  20. {
  21. jassert (bufferSize > 0);
  22. }
  23. AbstractFifo::~AbstractFifo() {}
  24. int AbstractFifo::getTotalSize() const noexcept { return bufferSize; }
  25. int AbstractFifo::getFreeSpace() const noexcept { return bufferSize - getNumReady(); }
  26. int AbstractFifo::getNumReady() const noexcept
  27. {
  28. const int vs = validStart.get();
  29. const int ve = validEnd.get();
  30. return ve >= vs ? (ve - vs) : (bufferSize - (vs - ve));
  31. }
  32. void AbstractFifo::reset() noexcept
  33. {
  34. validEnd = 0;
  35. validStart = 0;
  36. }
  37. void AbstractFifo::setTotalSize (int newSize) noexcept
  38. {
  39. jassert (newSize > 0);
  40. reset();
  41. bufferSize = newSize;
  42. }
  43. //==============================================================================
  44. void AbstractFifo::prepareToWrite (int numToWrite, int& startIndex1, int& blockSize1, int& startIndex2, int& blockSize2) const noexcept
  45. {
  46. const int vs = validStart.get();
  47. const int ve = validEnd.value;
  48. const int freeSpace = ve >= vs ? (bufferSize - (ve - vs)) : (vs - ve);
  49. numToWrite = jmin (numToWrite, freeSpace - 1);
  50. if (numToWrite <= 0)
  51. {
  52. startIndex1 = 0;
  53. startIndex2 = 0;
  54. blockSize1 = 0;
  55. blockSize2 = 0;
  56. }
  57. else
  58. {
  59. startIndex1 = ve;
  60. startIndex2 = 0;
  61. blockSize1 = jmin (bufferSize - ve, numToWrite);
  62. numToWrite -= blockSize1;
  63. blockSize2 = numToWrite <= 0 ? 0 : jmin (numToWrite, vs);
  64. }
  65. }
  66. void AbstractFifo::finishedWrite (int numWritten) noexcept
  67. {
  68. jassert (numWritten >= 0 && numWritten < bufferSize);
  69. int newEnd = validEnd.value + numWritten;
  70. if (newEnd >= bufferSize)
  71. newEnd -= bufferSize;
  72. validEnd = newEnd;
  73. }
  74. void AbstractFifo::prepareToRead (int numWanted, int& startIndex1, int& blockSize1, int& startIndex2, int& blockSize2) const noexcept
  75. {
  76. const int vs = validStart.value;
  77. const int ve = validEnd.get();
  78. const int numReady = ve >= vs ? (ve - vs) : (bufferSize - (vs - ve));
  79. numWanted = jmin (numWanted, numReady);
  80. if (numWanted <= 0)
  81. {
  82. startIndex1 = 0;
  83. startIndex2 = 0;
  84. blockSize1 = 0;
  85. blockSize2 = 0;
  86. }
  87. else
  88. {
  89. startIndex1 = vs;
  90. startIndex2 = 0;
  91. blockSize1 = jmin (bufferSize - vs, numWanted);
  92. numWanted -= blockSize1;
  93. blockSize2 = numWanted <= 0 ? 0 : jmin (numWanted, ve);
  94. }
  95. }
  96. void AbstractFifo::finishedRead (int numRead) noexcept
  97. {
  98. jassert (numRead >= 0 && numRead <= bufferSize);
  99. int newStart = validStart.value + numRead;
  100. if (newStart >= bufferSize)
  101. newStart -= bufferSize;
  102. validStart = newStart;
  103. }
  104. //==============================================================================
  105. //==============================================================================
  106. #if JUCE_UNIT_TESTS
  107. class AbstractFifoTests : public UnitTest
  108. {
  109. public:
  110. AbstractFifoTests() : UnitTest ("Abstract Fifo") {}
  111. class WriteThread : public Thread
  112. {
  113. public:
  114. WriteThread (AbstractFifo& fifo_, int* buffer_)
  115. : Thread ("fifo writer"), fifo (fifo_), buffer (buffer_)
  116. {
  117. startThread();
  118. }
  119. ~WriteThread()
  120. {
  121. stopThread (5000);
  122. }
  123. void run()
  124. {
  125. int n = 0;
  126. Random r;
  127. while (! threadShouldExit())
  128. {
  129. int num = r.nextInt (2000) + 1;
  130. int start1, size1, start2, size2;
  131. fifo.prepareToWrite (num, start1, size1, start2, size2);
  132. jassert (size1 >= 0 && size2 >= 0);
  133. jassert (size1 == 0 || (start1 >= 0 && start1 < fifo.getTotalSize()));
  134. jassert (size2 == 0 || (start2 >= 0 && start2 < fifo.getTotalSize()));
  135. int i;
  136. for (i = 0; i < size1; ++i)
  137. buffer [start1 + i] = n++;
  138. for (i = 0; i < size2; ++i)
  139. buffer [start2 + i] = n++;
  140. fifo.finishedWrite (size1 + size2);
  141. }
  142. }
  143. private:
  144. AbstractFifo& fifo;
  145. int* buffer;
  146. };
  147. void runTest()
  148. {
  149. beginTest ("AbstractFifo");
  150. int buffer [5000];
  151. AbstractFifo fifo (numElementsInArray (buffer));
  152. WriteThread writer (fifo, buffer);
  153. int n = 0;
  154. Random r;
  155. for (int count = 1000000; --count >= 0;)
  156. {
  157. int num = r.nextInt (6000) + 1;
  158. int start1, size1, start2, size2;
  159. fifo.prepareToRead (num, start1, size1, start2, size2);
  160. if (! (size1 >= 0 && size2 >= 0)
  161. && (size1 == 0 || (start1 >= 0 && start1 < fifo.getTotalSize()))
  162. && (size2 == 0 || (start2 >= 0 && start2 < fifo.getTotalSize())))
  163. {
  164. expect (false, "prepareToRead returned -ve values");
  165. break;
  166. }
  167. bool failed = false;
  168. int i;
  169. for (i = 0; i < size1; ++i)
  170. failed = (buffer [start1 + i] != n++) || failed;
  171. for (i = 0; i < size2; ++i)
  172. failed = (buffer [start2 + i] != n++) || failed;
  173. if (failed)
  174. {
  175. expect (false, "read values were incorrect");
  176. break;
  177. }
  178. fifo.finishedRead (size1 + size2);
  179. }
  180. }
  181. };
  182. static AbstractFifoTests fifoUnitTests;
  183. #endif