xref: /aosp_15_r20/external/deqp/framework/delibs/decpp/deBlockBuffer.hpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker #ifndef _DEBLOCKBUFFER_HPP
2*35238bceSAndroid Build Coastguard Worker #define _DEBLOCKBUFFER_HPP
3*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
4*35238bceSAndroid Build Coastguard Worker  * drawElements C++ Base Library
5*35238bceSAndroid Build Coastguard Worker  * -----------------------------
6*35238bceSAndroid Build Coastguard Worker  *
7*35238bceSAndroid Build Coastguard Worker  * Copyright 2014 The Android Open Source Project
8*35238bceSAndroid Build Coastguard Worker  *
9*35238bceSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
10*35238bceSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
11*35238bceSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
12*35238bceSAndroid Build Coastguard Worker  *
13*35238bceSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
14*35238bceSAndroid Build Coastguard Worker  *
15*35238bceSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
16*35238bceSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
17*35238bceSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18*35238bceSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
19*35238bceSAndroid Build Coastguard Worker  * limitations under the License.
20*35238bceSAndroid Build Coastguard Worker  *
21*35238bceSAndroid Build Coastguard Worker  *//*!
22*35238bceSAndroid Build Coastguard Worker  * \file
23*35238bceSAndroid Build Coastguard Worker  * \brief Block-based thread-safe queue.
24*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
25*35238bceSAndroid Build Coastguard Worker 
26*35238bceSAndroid Build Coastguard Worker #include "deBlockBuffer.hpp"
27*35238bceSAndroid Build Coastguard Worker #include "deMutex.hpp"
28*35238bceSAndroid Build Coastguard Worker #include "deSemaphore.h"
29*35238bceSAndroid Build Coastguard Worker 
30*35238bceSAndroid Build Coastguard Worker #include <exception>
31*35238bceSAndroid Build Coastguard Worker 
32*35238bceSAndroid Build Coastguard Worker namespace de
33*35238bceSAndroid Build Coastguard Worker {
34*35238bceSAndroid Build Coastguard Worker 
35*35238bceSAndroid Build Coastguard Worker void BlockBuffer_selfTest(void);
36*35238bceSAndroid Build Coastguard Worker 
37*35238bceSAndroid Build Coastguard Worker class BufferCanceledException : public std::exception
38*35238bceSAndroid Build Coastguard Worker {
39*35238bceSAndroid Build Coastguard Worker public:
BufferCanceledException(void)40*35238bceSAndroid Build Coastguard Worker     inline BufferCanceledException(void)
41*35238bceSAndroid Build Coastguard Worker     {
42*35238bceSAndroid Build Coastguard Worker     }
~BufferCanceledException(void)43*35238bceSAndroid Build Coastguard Worker     inline ~BufferCanceledException(void) throw()
44*35238bceSAndroid Build Coastguard Worker     {
45*35238bceSAndroid Build Coastguard Worker     }
46*35238bceSAndroid Build Coastguard Worker 
what(void) const47*35238bceSAndroid Build Coastguard Worker     const char *what(void) const throw()
48*35238bceSAndroid Build Coastguard Worker     {
49*35238bceSAndroid Build Coastguard Worker         return "BufferCanceledException";
50*35238bceSAndroid Build Coastguard Worker     }
51*35238bceSAndroid Build Coastguard Worker };
52*35238bceSAndroid Build Coastguard Worker 
53*35238bceSAndroid Build Coastguard Worker template <typename T>
54*35238bceSAndroid Build Coastguard Worker class BlockBuffer
55*35238bceSAndroid Build Coastguard Worker {
56*35238bceSAndroid Build Coastguard Worker public:
57*35238bceSAndroid Build Coastguard Worker     typedef BufferCanceledException CanceledException;
58*35238bceSAndroid Build Coastguard Worker 
59*35238bceSAndroid Build Coastguard Worker     BlockBuffer(int blockSize, int numBlocks);
60*35238bceSAndroid Build Coastguard Worker     ~BlockBuffer(void);
61*35238bceSAndroid Build Coastguard Worker 
62*35238bceSAndroid Build Coastguard Worker     void clear(void); //!< Resets buffer. Will block until pending writes and reads have completed.
63*35238bceSAndroid Build Coastguard Worker 
64*35238bceSAndroid Build Coastguard Worker     void write(int numElements, const T *elements);
65*35238bceSAndroid Build Coastguard Worker     int tryWrite(int numElements, const T *elements);
66*35238bceSAndroid Build Coastguard Worker     void flush(void);
67*35238bceSAndroid Build Coastguard Worker     bool tryFlush(void);
68*35238bceSAndroid Build Coastguard Worker 
69*35238bceSAndroid Build Coastguard Worker     void read(int numElements, T *elements);
70*35238bceSAndroid Build Coastguard Worker     int tryRead(int numElements, T *elements);
71*35238bceSAndroid Build Coastguard Worker 
72*35238bceSAndroid Build Coastguard Worker     void cancel(
73*35238bceSAndroid Build Coastguard Worker         void); //!< Sets buffer in canceled state. All (including pending) writes and reads will result in CanceledException.
isCanceled(void) const74*35238bceSAndroid Build Coastguard Worker     bool isCanceled(void) const
75*35238bceSAndroid Build Coastguard Worker     {
76*35238bceSAndroid Build Coastguard Worker         return !!m_canceled;
77*35238bceSAndroid Build Coastguard Worker     }
78*35238bceSAndroid Build Coastguard Worker 
79*35238bceSAndroid Build Coastguard Worker private:
80*35238bceSAndroid Build Coastguard Worker     BlockBuffer(const BlockBuffer &other);
81*35238bceSAndroid Build Coastguard Worker     BlockBuffer &operator=(const BlockBuffer &other);
82*35238bceSAndroid Build Coastguard Worker 
83*35238bceSAndroid Build Coastguard Worker     int writeToCurrentBlock(int numElements, const T *elements, bool blocking);
84*35238bceSAndroid Build Coastguard Worker     int readFromCurrentBlock(int numElements, T *elements, bool blocking);
85*35238bceSAndroid Build Coastguard Worker 
86*35238bceSAndroid Build Coastguard Worker     void flushWriteBlock(void);
87*35238bceSAndroid Build Coastguard Worker 
88*35238bceSAndroid Build Coastguard Worker     deSemaphore m_fill;  //!< Block fill count.
89*35238bceSAndroid Build Coastguard Worker     deSemaphore m_empty; //!< Block empty count.
90*35238bceSAndroid Build Coastguard Worker 
91*35238bceSAndroid Build Coastguard Worker     int m_writeBlock; //!< Current write block ndx.
92*35238bceSAndroid Build Coastguard Worker     int m_writePos;   //!< Position in block. 0 if block is not yet acquired.
93*35238bceSAndroid Build Coastguard Worker 
94*35238bceSAndroid Build Coastguard Worker     int m_readBlock; //!< Current read block ndx.
95*35238bceSAndroid Build Coastguard Worker     int m_readPos;   //!< Position in block. 0 if block is not yet acquired.
96*35238bceSAndroid Build Coastguard Worker 
97*35238bceSAndroid Build Coastguard Worker     int m_blockSize;
98*35238bceSAndroid Build Coastguard Worker     int m_numBlocks;
99*35238bceSAndroid Build Coastguard Worker 
100*35238bceSAndroid Build Coastguard Worker     T *m_elements;
101*35238bceSAndroid Build Coastguard Worker     int *m_numUsedInBlock;
102*35238bceSAndroid Build Coastguard Worker 
103*35238bceSAndroid Build Coastguard Worker     Mutex m_writeLock;
104*35238bceSAndroid Build Coastguard Worker     Mutex m_readLock;
105*35238bceSAndroid Build Coastguard Worker 
106*35238bceSAndroid Build Coastguard Worker     volatile uint32_t m_canceled;
107*35238bceSAndroid Build Coastguard Worker } DE_WARN_UNUSED_TYPE;
108*35238bceSAndroid Build Coastguard Worker 
109*35238bceSAndroid Build Coastguard Worker template <typename T>
BlockBuffer(int blockSize,int numBlocks)110*35238bceSAndroid Build Coastguard Worker BlockBuffer<T>::BlockBuffer(int blockSize, int numBlocks)
111*35238bceSAndroid Build Coastguard Worker     : m_fill(0)
112*35238bceSAndroid Build Coastguard Worker     , m_empty(0)
113*35238bceSAndroid Build Coastguard Worker     , m_writeBlock(0)
114*35238bceSAndroid Build Coastguard Worker     , m_writePos(0)
115*35238bceSAndroid Build Coastguard Worker     , m_readBlock(0)
116*35238bceSAndroid Build Coastguard Worker     , m_readPos(0)
117*35238bceSAndroid Build Coastguard Worker     , m_blockSize(blockSize)
118*35238bceSAndroid Build Coastguard Worker     , m_numBlocks(numBlocks)
119*35238bceSAndroid Build Coastguard Worker     , m_elements(DE_NULL)
120*35238bceSAndroid Build Coastguard Worker     , m_numUsedInBlock(DE_NULL)
121*35238bceSAndroid Build Coastguard Worker     , m_writeLock()
122*35238bceSAndroid Build Coastguard Worker     , m_readLock()
123*35238bceSAndroid Build Coastguard Worker     , m_canceled(false)
124*35238bceSAndroid Build Coastguard Worker {
125*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(blockSize > 0);
126*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(numBlocks > 0);
127*35238bceSAndroid Build Coastguard Worker 
128*35238bceSAndroid Build Coastguard Worker     try
129*35238bceSAndroid Build Coastguard Worker     {
130*35238bceSAndroid Build Coastguard Worker         m_elements       = new T[m_numBlocks * m_blockSize];
131*35238bceSAndroid Build Coastguard Worker         m_numUsedInBlock = new int[m_numBlocks];
132*35238bceSAndroid Build Coastguard Worker     }
133*35238bceSAndroid Build Coastguard Worker     catch (...)
134*35238bceSAndroid Build Coastguard Worker     {
135*35238bceSAndroid Build Coastguard Worker         delete[] m_elements;
136*35238bceSAndroid Build Coastguard Worker         delete[] m_numUsedInBlock;
137*35238bceSAndroid Build Coastguard Worker         throw;
138*35238bceSAndroid Build Coastguard Worker     }
139*35238bceSAndroid Build Coastguard Worker 
140*35238bceSAndroid Build Coastguard Worker     m_fill  = deSemaphore_create(0, DE_NULL);
141*35238bceSAndroid Build Coastguard Worker     m_empty = deSemaphore_create(numBlocks, DE_NULL);
142*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(m_fill && m_empty);
143*35238bceSAndroid Build Coastguard Worker }
144*35238bceSAndroid Build Coastguard Worker 
145*35238bceSAndroid Build Coastguard Worker template <typename T>
~BlockBuffer(void)146*35238bceSAndroid Build Coastguard Worker BlockBuffer<T>::~BlockBuffer(void)
147*35238bceSAndroid Build Coastguard Worker {
148*35238bceSAndroid Build Coastguard Worker     delete[] m_elements;
149*35238bceSAndroid Build Coastguard Worker     delete[] m_numUsedInBlock;
150*35238bceSAndroid Build Coastguard Worker 
151*35238bceSAndroid Build Coastguard Worker     deSemaphore_destroy(m_fill);
152*35238bceSAndroid Build Coastguard Worker     deSemaphore_destroy(m_empty);
153*35238bceSAndroid Build Coastguard Worker }
154*35238bceSAndroid Build Coastguard Worker 
155*35238bceSAndroid Build Coastguard Worker template <typename T>
clear(void)156*35238bceSAndroid Build Coastguard Worker void BlockBuffer<T>::clear(void)
157*35238bceSAndroid Build Coastguard Worker {
158*35238bceSAndroid Build Coastguard Worker     ScopedLock readLock(m_readLock);
159*35238bceSAndroid Build Coastguard Worker     ScopedLock writeLock(m_writeLock);
160*35238bceSAndroid Build Coastguard Worker 
161*35238bceSAndroid Build Coastguard Worker     deSemaphore_destroy(m_fill);
162*35238bceSAndroid Build Coastguard Worker     deSemaphore_destroy(m_empty);
163*35238bceSAndroid Build Coastguard Worker 
164*35238bceSAndroid Build Coastguard Worker     m_fill       = deSemaphore_create(0, DE_NULL);
165*35238bceSAndroid Build Coastguard Worker     m_empty      = deSemaphore_create(m_numBlocks, DE_NULL);
166*35238bceSAndroid Build Coastguard Worker     m_writeBlock = 0;
167*35238bceSAndroid Build Coastguard Worker     m_writePos   = 0;
168*35238bceSAndroid Build Coastguard Worker     m_readBlock  = 0;
169*35238bceSAndroid Build Coastguard Worker     m_readPos    = 0;
170*35238bceSAndroid Build Coastguard Worker     m_canceled   = false;
171*35238bceSAndroid Build Coastguard Worker 
172*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(m_fill && m_empty);
173*35238bceSAndroid Build Coastguard Worker }
174*35238bceSAndroid Build Coastguard Worker 
175*35238bceSAndroid Build Coastguard Worker template <typename T>
cancel(void)176*35238bceSAndroid Build Coastguard Worker void BlockBuffer<T>::cancel(void)
177*35238bceSAndroid Build Coastguard Worker {
178*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(!m_canceled);
179*35238bceSAndroid Build Coastguard Worker     m_canceled = true;
180*35238bceSAndroid Build Coastguard Worker 
181*35238bceSAndroid Build Coastguard Worker     deSemaphore_increment(m_empty);
182*35238bceSAndroid Build Coastguard Worker     deSemaphore_increment(m_fill);
183*35238bceSAndroid Build Coastguard Worker }
184*35238bceSAndroid Build Coastguard Worker 
185*35238bceSAndroid Build Coastguard Worker template <typename T>
writeToCurrentBlock(int numElements,const T * elements,bool blocking)186*35238bceSAndroid Build Coastguard Worker int BlockBuffer<T>::writeToCurrentBlock(int numElements, const T *elements, bool blocking)
187*35238bceSAndroid Build Coastguard Worker {
188*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(numElements > 0 && elements != DE_NULL);
189*35238bceSAndroid Build Coastguard Worker 
190*35238bceSAndroid Build Coastguard Worker     if (m_writePos == 0)
191*35238bceSAndroid Build Coastguard Worker     {
192*35238bceSAndroid Build Coastguard Worker         /* Write thread doesn't own current block - need to acquire. */
193*35238bceSAndroid Build Coastguard Worker         if (blocking)
194*35238bceSAndroid Build Coastguard Worker             deSemaphore_decrement(m_empty);
195*35238bceSAndroid Build Coastguard Worker         else
196*35238bceSAndroid Build Coastguard Worker         {
197*35238bceSAndroid Build Coastguard Worker             if (!deSemaphore_tryDecrement(m_empty))
198*35238bceSAndroid Build Coastguard Worker                 return 0;
199*35238bceSAndroid Build Coastguard Worker         }
200*35238bceSAndroid Build Coastguard Worker 
201*35238bceSAndroid Build Coastguard Worker         /* Check for canceled bit. */
202*35238bceSAndroid Build Coastguard Worker         if (m_canceled)
203*35238bceSAndroid Build Coastguard Worker         {
204*35238bceSAndroid Build Coastguard Worker             // \todo [2012-07-06 pyry] A bit hackish to assume that write lock is not freed if exception is thrown out here.
205*35238bceSAndroid Build Coastguard Worker             deSemaphore_increment(m_empty);
206*35238bceSAndroid Build Coastguard Worker             m_writeLock.unlock();
207*35238bceSAndroid Build Coastguard Worker             throw CanceledException();
208*35238bceSAndroid Build Coastguard Worker         }
209*35238bceSAndroid Build Coastguard Worker     }
210*35238bceSAndroid Build Coastguard Worker 
211*35238bceSAndroid Build Coastguard Worker     /* Write thread owns current block. */
212*35238bceSAndroid Build Coastguard Worker     T *block       = m_elements + m_writeBlock * m_blockSize;
213*35238bceSAndroid Build Coastguard Worker     int numToWrite = de::min(numElements, m_blockSize - m_writePos);
214*35238bceSAndroid Build Coastguard Worker 
215*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(numToWrite > 0);
216*35238bceSAndroid Build Coastguard Worker 
217*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < numToWrite; ndx++)
218*35238bceSAndroid Build Coastguard Worker         block[m_writePos + ndx] = elements[ndx];
219*35238bceSAndroid Build Coastguard Worker 
220*35238bceSAndroid Build Coastguard Worker     m_writePos += numToWrite;
221*35238bceSAndroid Build Coastguard Worker 
222*35238bceSAndroid Build Coastguard Worker     if (m_writePos == m_blockSize)
223*35238bceSAndroid Build Coastguard Worker         flushWriteBlock(); /* Flush current write block. */
224*35238bceSAndroid Build Coastguard Worker 
225*35238bceSAndroid Build Coastguard Worker     return numToWrite;
226*35238bceSAndroid Build Coastguard Worker }
227*35238bceSAndroid Build Coastguard Worker 
228*35238bceSAndroid Build Coastguard Worker template <typename T>
readFromCurrentBlock(int numElements,T * elements,bool blocking)229*35238bceSAndroid Build Coastguard Worker int BlockBuffer<T>::readFromCurrentBlock(int numElements, T *elements, bool blocking)
230*35238bceSAndroid Build Coastguard Worker {
231*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(numElements > 0 && elements != DE_NULL);
232*35238bceSAndroid Build Coastguard Worker 
233*35238bceSAndroid Build Coastguard Worker     if (m_readPos == 0)
234*35238bceSAndroid Build Coastguard Worker     {
235*35238bceSAndroid Build Coastguard Worker         /* Read thread doesn't own current block - need to acquire. */
236*35238bceSAndroid Build Coastguard Worker         if (blocking)
237*35238bceSAndroid Build Coastguard Worker             deSemaphore_decrement(m_fill);
238*35238bceSAndroid Build Coastguard Worker         else
239*35238bceSAndroid Build Coastguard Worker         {
240*35238bceSAndroid Build Coastguard Worker             if (!deSemaphore_tryDecrement(m_fill))
241*35238bceSAndroid Build Coastguard Worker                 return 0;
242*35238bceSAndroid Build Coastguard Worker         }
243*35238bceSAndroid Build Coastguard Worker 
244*35238bceSAndroid Build Coastguard Worker         /* Check for canceled bit. */
245*35238bceSAndroid Build Coastguard Worker         if (m_canceled)
246*35238bceSAndroid Build Coastguard Worker         {
247*35238bceSAndroid Build Coastguard Worker             // \todo [2012-07-06 pyry] A bit hackish to assume that read lock is not freed if exception is thrown out here.
248*35238bceSAndroid Build Coastguard Worker             deSemaphore_increment(m_fill);
249*35238bceSAndroid Build Coastguard Worker             m_readLock.unlock();
250*35238bceSAndroid Build Coastguard Worker             throw CanceledException();
251*35238bceSAndroid Build Coastguard Worker         }
252*35238bceSAndroid Build Coastguard Worker     }
253*35238bceSAndroid Build Coastguard Worker 
254*35238bceSAndroid Build Coastguard Worker     /* Read thread now owns current block. */
255*35238bceSAndroid Build Coastguard Worker     const T *block     = m_elements + m_readBlock * m_blockSize;
256*35238bceSAndroid Build Coastguard Worker     int numUsedInBlock = m_numUsedInBlock[m_readBlock];
257*35238bceSAndroid Build Coastguard Worker     int numToRead      = de::min(numElements, numUsedInBlock - m_readPos);
258*35238bceSAndroid Build Coastguard Worker 
259*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(numToRead > 0);
260*35238bceSAndroid Build Coastguard Worker 
261*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < numToRead; ndx++)
262*35238bceSAndroid Build Coastguard Worker         elements[ndx] = block[m_readPos + ndx];
263*35238bceSAndroid Build Coastguard Worker 
264*35238bceSAndroid Build Coastguard Worker     m_readPos += numToRead;
265*35238bceSAndroid Build Coastguard Worker 
266*35238bceSAndroid Build Coastguard Worker     if (m_readPos == numUsedInBlock)
267*35238bceSAndroid Build Coastguard Worker     {
268*35238bceSAndroid Build Coastguard Worker         /* Free current read block and advance. */
269*35238bceSAndroid Build Coastguard Worker         m_readBlock = (m_readBlock + 1) % m_numBlocks;
270*35238bceSAndroid Build Coastguard Worker         m_readPos   = 0;
271*35238bceSAndroid Build Coastguard Worker         deSemaphore_increment(m_empty);
272*35238bceSAndroid Build Coastguard Worker     }
273*35238bceSAndroid Build Coastguard Worker 
274*35238bceSAndroid Build Coastguard Worker     return numToRead;
275*35238bceSAndroid Build Coastguard Worker }
276*35238bceSAndroid Build Coastguard Worker 
277*35238bceSAndroid Build Coastguard Worker template <typename T>
tryWrite(int numElements,const T * elements)278*35238bceSAndroid Build Coastguard Worker int BlockBuffer<T>::tryWrite(int numElements, const T *elements)
279*35238bceSAndroid Build Coastguard Worker {
280*35238bceSAndroid Build Coastguard Worker     int numWritten = 0;
281*35238bceSAndroid Build Coastguard Worker 
282*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(numElements > 0 && elements != DE_NULL);
283*35238bceSAndroid Build Coastguard Worker 
284*35238bceSAndroid Build Coastguard Worker     if (m_canceled)
285*35238bceSAndroid Build Coastguard Worker         throw CanceledException();
286*35238bceSAndroid Build Coastguard Worker 
287*35238bceSAndroid Build Coastguard Worker     if (!m_writeLock.tryLock())
288*35238bceSAndroid Build Coastguard Worker         return numWritten;
289*35238bceSAndroid Build Coastguard Worker 
290*35238bceSAndroid Build Coastguard Worker     while (numWritten < numElements)
291*35238bceSAndroid Build Coastguard Worker     {
292*35238bceSAndroid Build Coastguard Worker         int ret = writeToCurrentBlock(numElements - numWritten, elements + numWritten, false /* non-blocking */);
293*35238bceSAndroid Build Coastguard Worker 
294*35238bceSAndroid Build Coastguard Worker         if (ret == 0)
295*35238bceSAndroid Build Coastguard Worker             break; /* Write failed. */
296*35238bceSAndroid Build Coastguard Worker 
297*35238bceSAndroid Build Coastguard Worker         numWritten += ret;
298*35238bceSAndroid Build Coastguard Worker     }
299*35238bceSAndroid Build Coastguard Worker 
300*35238bceSAndroid Build Coastguard Worker     m_writeLock.unlock();
301*35238bceSAndroid Build Coastguard Worker 
302*35238bceSAndroid Build Coastguard Worker     return numWritten;
303*35238bceSAndroid Build Coastguard Worker }
304*35238bceSAndroid Build Coastguard Worker 
305*35238bceSAndroid Build Coastguard Worker template <typename T>
write(int numElements,const T * elements)306*35238bceSAndroid Build Coastguard Worker void BlockBuffer<T>::write(int numElements, const T *elements)
307*35238bceSAndroid Build Coastguard Worker {
308*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(numElements > 0 && elements != DE_NULL);
309*35238bceSAndroid Build Coastguard Worker 
310*35238bceSAndroid Build Coastguard Worker     if (m_canceled)
311*35238bceSAndroid Build Coastguard Worker         throw CanceledException();
312*35238bceSAndroid Build Coastguard Worker 
313*35238bceSAndroid Build Coastguard Worker     m_writeLock.lock();
314*35238bceSAndroid Build Coastguard Worker 
315*35238bceSAndroid Build Coastguard Worker     int numWritten = 0;
316*35238bceSAndroid Build Coastguard Worker     while (numWritten < numElements)
317*35238bceSAndroid Build Coastguard Worker         numWritten += writeToCurrentBlock(numElements - numWritten, elements + numWritten, true /* blocking */);
318*35238bceSAndroid Build Coastguard Worker 
319*35238bceSAndroid Build Coastguard Worker     m_writeLock.unlock();
320*35238bceSAndroid Build Coastguard Worker }
321*35238bceSAndroid Build Coastguard Worker 
322*35238bceSAndroid Build Coastguard Worker template <typename T>
flush(void)323*35238bceSAndroid Build Coastguard Worker void BlockBuffer<T>::flush(void)
324*35238bceSAndroid Build Coastguard Worker {
325*35238bceSAndroid Build Coastguard Worker     m_writeLock.lock();
326*35238bceSAndroid Build Coastguard Worker 
327*35238bceSAndroid Build Coastguard Worker     if (m_writePos > 0)
328*35238bceSAndroid Build Coastguard Worker         flushWriteBlock();
329*35238bceSAndroid Build Coastguard Worker 
330*35238bceSAndroid Build Coastguard Worker     m_writeLock.unlock();
331*35238bceSAndroid Build Coastguard Worker }
332*35238bceSAndroid Build Coastguard Worker 
333*35238bceSAndroid Build Coastguard Worker template <typename T>
tryFlush(void)334*35238bceSAndroid Build Coastguard Worker bool BlockBuffer<T>::tryFlush(void)
335*35238bceSAndroid Build Coastguard Worker {
336*35238bceSAndroid Build Coastguard Worker     if (!m_writeLock.tryLock())
337*35238bceSAndroid Build Coastguard Worker         return false;
338*35238bceSAndroid Build Coastguard Worker 
339*35238bceSAndroid Build Coastguard Worker     if (m_writePos > 0)
340*35238bceSAndroid Build Coastguard Worker         flushWriteBlock();
341*35238bceSAndroid Build Coastguard Worker 
342*35238bceSAndroid Build Coastguard Worker     m_writeLock.unlock();
343*35238bceSAndroid Build Coastguard Worker 
344*35238bceSAndroid Build Coastguard Worker     return true;
345*35238bceSAndroid Build Coastguard Worker }
346*35238bceSAndroid Build Coastguard Worker 
347*35238bceSAndroid Build Coastguard Worker template <typename T>
flushWriteBlock(void)348*35238bceSAndroid Build Coastguard Worker void BlockBuffer<T>::flushWriteBlock(void)
349*35238bceSAndroid Build Coastguard Worker {
350*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(de::inRange(m_writePos, 1, m_blockSize));
351*35238bceSAndroid Build Coastguard Worker 
352*35238bceSAndroid Build Coastguard Worker     m_numUsedInBlock[m_writeBlock] = m_writePos;
353*35238bceSAndroid Build Coastguard Worker     m_writeBlock                   = (m_writeBlock + 1) % m_numBlocks;
354*35238bceSAndroid Build Coastguard Worker     m_writePos                     = 0;
355*35238bceSAndroid Build Coastguard Worker     deSemaphore_increment(m_fill);
356*35238bceSAndroid Build Coastguard Worker }
357*35238bceSAndroid Build Coastguard Worker 
358*35238bceSAndroid Build Coastguard Worker template <typename T>
tryRead(int numElements,T * elements)359*35238bceSAndroid Build Coastguard Worker int BlockBuffer<T>::tryRead(int numElements, T *elements)
360*35238bceSAndroid Build Coastguard Worker {
361*35238bceSAndroid Build Coastguard Worker     int numRead = 0;
362*35238bceSAndroid Build Coastguard Worker 
363*35238bceSAndroid Build Coastguard Worker     if (m_canceled)
364*35238bceSAndroid Build Coastguard Worker         throw CanceledException();
365*35238bceSAndroid Build Coastguard Worker 
366*35238bceSAndroid Build Coastguard Worker     if (!m_readLock.tryLock())
367*35238bceSAndroid Build Coastguard Worker         return numRead;
368*35238bceSAndroid Build Coastguard Worker 
369*35238bceSAndroid Build Coastguard Worker     while (numRead < numElements)
370*35238bceSAndroid Build Coastguard Worker     {
371*35238bceSAndroid Build Coastguard Worker         int ret = readFromCurrentBlock(numElements - numRead, &elements[numRead], false /* non-blocking */);
372*35238bceSAndroid Build Coastguard Worker 
373*35238bceSAndroid Build Coastguard Worker         if (ret == 0)
374*35238bceSAndroid Build Coastguard Worker             break; /* Failed. */
375*35238bceSAndroid Build Coastguard Worker 
376*35238bceSAndroid Build Coastguard Worker         numRead += ret;
377*35238bceSAndroid Build Coastguard Worker     }
378*35238bceSAndroid Build Coastguard Worker 
379*35238bceSAndroid Build Coastguard Worker     m_readLock.unlock();
380*35238bceSAndroid Build Coastguard Worker 
381*35238bceSAndroid Build Coastguard Worker     return numRead;
382*35238bceSAndroid Build Coastguard Worker }
383*35238bceSAndroid Build Coastguard Worker 
384*35238bceSAndroid Build Coastguard Worker template <typename T>
read(int numElements,T * elements)385*35238bceSAndroid Build Coastguard Worker void BlockBuffer<T>::read(int numElements, T *elements)
386*35238bceSAndroid Build Coastguard Worker {
387*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(numElements > 0 && elements != DE_NULL);
388*35238bceSAndroid Build Coastguard Worker 
389*35238bceSAndroid Build Coastguard Worker     if (m_canceled)
390*35238bceSAndroid Build Coastguard Worker         throw CanceledException();
391*35238bceSAndroid Build Coastguard Worker 
392*35238bceSAndroid Build Coastguard Worker     m_readLock.lock();
393*35238bceSAndroid Build Coastguard Worker 
394*35238bceSAndroid Build Coastguard Worker     int numRead = 0;
395*35238bceSAndroid Build Coastguard Worker     while (numRead < numElements)
396*35238bceSAndroid Build Coastguard Worker         numRead += readFromCurrentBlock(numElements - numRead, &elements[numRead], true /* blocking */);
397*35238bceSAndroid Build Coastguard Worker 
398*35238bceSAndroid Build Coastguard Worker     m_readLock.unlock();
399*35238bceSAndroid Build Coastguard Worker }
400*35238bceSAndroid Build Coastguard Worker 
401*35238bceSAndroid Build Coastguard Worker } // namespace de
402*35238bceSAndroid Build Coastguard Worker 
403*35238bceSAndroid Build Coastguard Worker #endif // _DEBLOCKBUFFER_HPP
404