1*35238bceSAndroid Build Coastguard Worker #ifndef _DETHREADSAFERINGBUFFER_HPP 2*35238bceSAndroid Build Coastguard Worker #define _DETHREADSAFERINGBUFFER_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 Thread-safe ring buffer template. 24*35238bceSAndroid Build Coastguard Worker *//*--------------------------------------------------------------------*/ 25*35238bceSAndroid Build Coastguard Worker 26*35238bceSAndroid Build Coastguard Worker #include "deDefs.hpp" 27*35238bceSAndroid Build Coastguard Worker #include "deMutex.hpp" 28*35238bceSAndroid Build Coastguard Worker #include "deSemaphore.hpp" 29*35238bceSAndroid Build Coastguard Worker 30*35238bceSAndroid Build Coastguard Worker #include <vector> 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 ThreadSafeRingBuffer_selfTest(void); 36*35238bceSAndroid Build Coastguard Worker 37*35238bceSAndroid Build Coastguard Worker /** Thread-safe ring buffer template. */ 38*35238bceSAndroid Build Coastguard Worker template <typename T> 39*35238bceSAndroid Build Coastguard Worker class ThreadSafeRingBuffer 40*35238bceSAndroid Build Coastguard Worker { 41*35238bceSAndroid Build Coastguard Worker public: 42*35238bceSAndroid Build Coastguard Worker ThreadSafeRingBuffer(size_t size); ~ThreadSafeRingBuffer(void)43*35238bceSAndroid Build Coastguard Worker ~ThreadSafeRingBuffer(void) 44*35238bceSAndroid Build Coastguard Worker { 45*35238bceSAndroid Build Coastguard Worker } 46*35238bceSAndroid Build Coastguard Worker 47*35238bceSAndroid Build Coastguard Worker void pushFront(const T &elem); 48*35238bceSAndroid Build Coastguard Worker bool tryPushFront(const T &elem); 49*35238bceSAndroid Build Coastguard Worker T popBack(void); 50*35238bceSAndroid Build Coastguard Worker bool tryPopBack(T &dst); 51*35238bceSAndroid Build Coastguard Worker 52*35238bceSAndroid Build Coastguard Worker protected: 53*35238bceSAndroid Build Coastguard Worker void pushFrontInternal(const T &elem); 54*35238bceSAndroid Build Coastguard Worker T popBackInternal(void); 55*35238bceSAndroid Build Coastguard Worker 56*35238bceSAndroid Build Coastguard Worker const size_t m_size; 57*35238bceSAndroid Build Coastguard Worker std::vector<T> m_elements; 58*35238bceSAndroid Build Coastguard Worker 59*35238bceSAndroid Build Coastguard Worker size_t m_front; 60*35238bceSAndroid Build Coastguard Worker size_t m_back; 61*35238bceSAndroid Build Coastguard Worker 62*35238bceSAndroid Build Coastguard Worker Mutex m_writeMutex; 63*35238bceSAndroid Build Coastguard Worker Mutex m_readMutex; 64*35238bceSAndroid Build Coastguard Worker 65*35238bceSAndroid Build Coastguard Worker Semaphore m_fill; 66*35238bceSAndroid Build Coastguard Worker Semaphore m_empty; 67*35238bceSAndroid Build Coastguard Worker }; 68*35238bceSAndroid Build Coastguard Worker 69*35238bceSAndroid Build Coastguard Worker // ThreadSafeRingBuffer implementation. 70*35238bceSAndroid Build Coastguard Worker 71*35238bceSAndroid Build Coastguard Worker template <typename T> ThreadSafeRingBuffer(size_t size)72*35238bceSAndroid Build Coastguard WorkerThreadSafeRingBuffer<T>::ThreadSafeRingBuffer(size_t size) 73*35238bceSAndroid Build Coastguard Worker : m_size(size + 1) 74*35238bceSAndroid Build Coastguard Worker , m_elements(m_size) 75*35238bceSAndroid Build Coastguard Worker , m_front(0) 76*35238bceSAndroid Build Coastguard Worker , m_back(0) 77*35238bceSAndroid Build Coastguard Worker , m_fill(0) 78*35238bceSAndroid Build Coastguard Worker , m_empty((int)size) 79*35238bceSAndroid Build Coastguard Worker { 80*35238bceSAndroid Build Coastguard Worker // Semaphores currently only support INT_MAX 81*35238bceSAndroid Build Coastguard Worker DE_ASSERT(size > 0 && size < 0x7fffffff); 82*35238bceSAndroid Build Coastguard Worker } 83*35238bceSAndroid Build Coastguard Worker 84*35238bceSAndroid Build Coastguard Worker template <typename T> pushFrontInternal(const T & elem)85*35238bceSAndroid Build Coastguard Workerinline void ThreadSafeRingBuffer<T>::pushFrontInternal(const T &elem) 86*35238bceSAndroid Build Coastguard Worker { 87*35238bceSAndroid Build Coastguard Worker m_elements[m_front] = elem; 88*35238bceSAndroid Build Coastguard Worker m_front = (m_front + 1) % m_size; 89*35238bceSAndroid Build Coastguard Worker } 90*35238bceSAndroid Build Coastguard Worker 91*35238bceSAndroid Build Coastguard Worker template <typename T> popBackInternal()92*35238bceSAndroid Build Coastguard Workerinline T ThreadSafeRingBuffer<T>::popBackInternal() 93*35238bceSAndroid Build Coastguard Worker { 94*35238bceSAndroid Build Coastguard Worker const size_t ndx = m_back; 95*35238bceSAndroid Build Coastguard Worker m_back = (m_back + 1) % m_size; 96*35238bceSAndroid Build Coastguard Worker return m_elements[ndx]; 97*35238bceSAndroid Build Coastguard Worker } 98*35238bceSAndroid Build Coastguard Worker 99*35238bceSAndroid Build Coastguard Worker template <typename T> pushFront(const T & elem)100*35238bceSAndroid Build Coastguard Workervoid ThreadSafeRingBuffer<T>::pushFront(const T &elem) 101*35238bceSAndroid Build Coastguard Worker { 102*35238bceSAndroid Build Coastguard Worker m_writeMutex.lock(); 103*35238bceSAndroid Build Coastguard Worker m_empty.decrement(); 104*35238bceSAndroid Build Coastguard Worker pushFrontInternal(elem); 105*35238bceSAndroid Build Coastguard Worker m_fill.increment(); 106*35238bceSAndroid Build Coastguard Worker m_writeMutex.unlock(); 107*35238bceSAndroid Build Coastguard Worker } 108*35238bceSAndroid Build Coastguard Worker 109*35238bceSAndroid Build Coastguard Worker template <typename T> tryPushFront(const T & elem)110*35238bceSAndroid Build Coastguard Workerbool ThreadSafeRingBuffer<T>::tryPushFront(const T &elem) 111*35238bceSAndroid Build Coastguard Worker { 112*35238bceSAndroid Build Coastguard Worker if (!m_writeMutex.tryLock()) 113*35238bceSAndroid Build Coastguard Worker return false; 114*35238bceSAndroid Build Coastguard Worker 115*35238bceSAndroid Build Coastguard Worker const bool success = m_empty.tryDecrement(); 116*35238bceSAndroid Build Coastguard Worker 117*35238bceSAndroid Build Coastguard Worker if (success) 118*35238bceSAndroid Build Coastguard Worker { 119*35238bceSAndroid Build Coastguard Worker pushFrontInternal(elem); 120*35238bceSAndroid Build Coastguard Worker m_fill.increment(); 121*35238bceSAndroid Build Coastguard Worker } 122*35238bceSAndroid Build Coastguard Worker 123*35238bceSAndroid Build Coastguard Worker m_writeMutex.unlock(); 124*35238bceSAndroid Build Coastguard Worker return success; 125*35238bceSAndroid Build Coastguard Worker } 126*35238bceSAndroid Build Coastguard Worker 127*35238bceSAndroid Build Coastguard Worker template <typename T> popBack()128*35238bceSAndroid Build Coastguard WorkerT ThreadSafeRingBuffer<T>::popBack() 129*35238bceSAndroid Build Coastguard Worker { 130*35238bceSAndroid Build Coastguard Worker m_readMutex.lock(); 131*35238bceSAndroid Build Coastguard Worker m_fill.decrement(); 132*35238bceSAndroid Build Coastguard Worker T elem = popBackInternal(); 133*35238bceSAndroid Build Coastguard Worker m_empty.increment(); 134*35238bceSAndroid Build Coastguard Worker m_readMutex.unlock(); 135*35238bceSAndroid Build Coastguard Worker return elem; 136*35238bceSAndroid Build Coastguard Worker } 137*35238bceSAndroid Build Coastguard Worker 138*35238bceSAndroid Build Coastguard Worker template <typename T> tryPopBack(T & dst)139*35238bceSAndroid Build Coastguard Workerbool ThreadSafeRingBuffer<T>::tryPopBack(T &dst) 140*35238bceSAndroid Build Coastguard Worker { 141*35238bceSAndroid Build Coastguard Worker if (!m_readMutex.tryLock()) 142*35238bceSAndroid Build Coastguard Worker return false; 143*35238bceSAndroid Build Coastguard Worker 144*35238bceSAndroid Build Coastguard Worker bool success = m_fill.tryDecrement(); 145*35238bceSAndroid Build Coastguard Worker 146*35238bceSAndroid Build Coastguard Worker if (success) 147*35238bceSAndroid Build Coastguard Worker { 148*35238bceSAndroid Build Coastguard Worker dst = popBackInternal(); 149*35238bceSAndroid Build Coastguard Worker m_empty.increment(); 150*35238bceSAndroid Build Coastguard Worker } 151*35238bceSAndroid Build Coastguard Worker 152*35238bceSAndroid Build Coastguard Worker m_readMutex.unlock(); 153*35238bceSAndroid Build Coastguard Worker 154*35238bceSAndroid Build Coastguard Worker return success; 155*35238bceSAndroid Build Coastguard Worker } 156*35238bceSAndroid Build Coastguard Worker 157*35238bceSAndroid Build Coastguard Worker } // namespace de 158*35238bceSAndroid Build Coastguard Worker 159*35238bceSAndroid Build Coastguard Worker #endif // _DETHREADSAFERINGBUFFER_HPP 160