2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #ifndef __JUCE_ABSTRACTFIFO_JUCEHEADER__
27 #define __JUCE_ABSTRACTFIFO_JUCEHEADER__
29 #include "../memory/juce_Atomic.h"
32 //==============================================================================
34 Encapsulates the logic required to implement a lock-free FIFO.
36 This class handles the logic needed when building a single-reader, single-writer FIFO.
38 It doesn't actually hold any data itself, but your FIFO class can use one of these to manage
39 its position and status when reading or writing to it.
41 To use it, you can call prepareToWrite() to determine the position within your own buffer that
42 an incoming block of data should be stored, and prepareToRead() to find out when the next
43 outgoing block should be read from.
50 MyFifo() : abstractFifo (1024)
54 void addToFifo (const int* someData, int numItems)
56 int start1, size1, start2, size2;
57 prepareToWrite (numItems, start1, size1, start2, size2);
60 copySomeData (myBuffer + start1, someData, size1);
63 copySomeData (myBuffer + start2, someData + size1, size2);
65 finishedWrite (size1 + size2);
68 void readFromFifo (int* someData, int numItems)
70 int start1, size1, start2, size2;
71 prepareToRead (numSamples, start1, size1, start2, size2);
74 copySomeData (someData, myBuffer + start1, size1);
77 copySomeData (someData + size1, myBuffer + start2, size2);
79 finishedRead (size1 + size2);
83 AbstractFifo abstractFifo;
88 class JUCE_API AbstractFifo
91 //==============================================================================
92 /** Creates a FIFO to manage a buffer with the specified capacity. */
93 AbstractFifo (int capacity
) noexcept
;
98 //==============================================================================
99 /** Returns the total size of the buffer being managed. */
100 int getTotalSize() const noexcept
;
102 /** Returns the number of items that can currently be added to the buffer without it overflowing. */
103 int getFreeSpace() const noexcept
;
105 /** Returns the number of items that can currently be read from the buffer. */
106 int getNumReady() const noexcept
;
108 /** Clears the buffer positions, so that it appears empty. */
109 void reset() noexcept
;
111 /** Changes the buffer's total size.
112 Note that this isn't thread-safe, so don't call it if there's any danger that it
113 might overlap with a call to any other method in this class!
115 void setTotalSize (int newSize
) noexcept
;
117 //==============================================================================
118 /** Returns the location within the buffer at which an incoming block of data should be written.
120 Because the section of data that you want to add to the buffer may overlap the end
121 and wrap around to the start, two blocks within your buffer are returned, and you
122 should copy your data into the first one, with any remaining data spilling over into
125 If the number of items you ask for is too large to fit within the buffer's free space, then
126 blockSize1 + blockSize2 may add up to a lower value than numToWrite. If this happens, you
127 may decide to keep waiting and re-trying the method until there's enough space available.
129 After calling this method, if you choose to write your data into the blocks returned, you
130 must call finishedWrite() to tell the FIFO how much data you actually added.
134 void addToFifo (const int* someData, int numItems)
136 int start1, size1, start2, size2;
137 prepareToWrite (numItems, start1, size1, start2, size2);
140 copySomeData (myBuffer + start1, someData, size1);
143 copySomeData (myBuffer + start2, someData + size1, size2);
145 finishedWrite (size1 + size2);
149 @param numToWrite indicates how many items you'd like to add to the buffer
150 @param startIndex1 on exit, this will contain the start index in your buffer at which your data should be written
151 @param blockSize1 on exit, this indicates how many items can be written to the block starting at startIndex1
152 @param startIndex2 on exit, this will contain the start index in your buffer at which any data that didn't fit into
153 the first block should be written
154 @param blockSize2 on exit, this indicates how many items can be written to the block starting at startIndex2
157 void prepareToWrite (int numToWrite
, int& startIndex1
, int& blockSize1
, int& startIndex2
, int& blockSize2
) const noexcept
;
159 /** Called after reading from the FIFO, to indicate that this many items have been added.
162 void finishedWrite (int numWritten
) noexcept
;
164 /** Returns the location within the buffer from which the next block of data should be read.
166 Because the section of data that you want to read from the buffer may overlap the end
167 and wrap around to the start, two blocks within your buffer are returned, and you
168 should read from both of them.
170 If the number of items you ask for is greater than the amount of data available, then
171 blockSize1 + blockSize2 may add up to a lower value than numWanted. If this happens, you
172 may decide to keep waiting and re-trying the method until there's enough data available.
174 After calling this method, if you choose to read the data, you must call finishedRead() to
175 tell the FIFO how much data you have consumed.
179 void readFromFifo (int* someData, int numItems)
181 int start1, size1, start2, size2;
182 prepareToRead (numSamples, start1, size1, start2, size2);
185 copySomeData (someData, myBuffer + start1, size1);
188 copySomeData (someData + size1, myBuffer + start2, size2);
190 finishedRead (size1 + size2);
194 @param numWanted indicates how many items you'd like to add to the buffer
195 @param startIndex1 on exit, this will contain the start index in your buffer at which your data should be written
196 @param blockSize1 on exit, this indicates how many items can be written to the block starting at startIndex1
197 @param startIndex2 on exit, this will contain the start index in your buffer at which any data that didn't fit into
198 the first block should be written
199 @param blockSize2 on exit, this indicates how many items can be written to the block starting at startIndex2
202 void prepareToRead (int numWanted
, int& startIndex1
, int& blockSize1
, int& startIndex2
, int& blockSize2
) const noexcept
;
204 /** Called after reading from the FIFO, to indicate that this many items have now been consumed.
207 void finishedRead (int numRead
) noexcept
;
211 //==============================================================================
213 Atomic
<int> validStart
, validEnd
;
215 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AbstractFifo
);
219 #endif // __JUCE_ABSTRACTFIFO_JUCEHEADER__