• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #ifndef _DETHREADSAFERINGBUFFER_HPP
2 #define _DETHREADSAFERINGBUFFER_HPP
3 /*-------------------------------------------------------------------------
4  * drawElements C++ Base Library
5  * -----------------------------
6  *
7  * Copyright 2014 The Android Open Source Project
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief Thread-safe ring buffer template.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "deDefs.hpp"
27 #include "deMutex.hpp"
28 #include "deSemaphore.hpp"
29 
30 #include <vector>
31 
32 namespace de
33 {
34 
35 void ThreadSafeRingBuffer_selfTest (void);
36 
37 /** Thread-safe ring buffer template. */
38 template <typename T>
39 class ThreadSafeRingBuffer
40 {
41 public:
42 					ThreadSafeRingBuffer	(size_t size);
~ThreadSafeRingBuffer(void)43 					~ThreadSafeRingBuffer	(void) {}
44 
45 	void			pushFront				(const T& elem);
46 	bool			tryPushFront			(const T& elem);
47 	T				popBack					(void);
48 	bool			tryPopBack				(T& dst);
49 
50 protected:
51 	void			pushFrontInternal		(const T& elem);
52 	T				popBackInternal			(void);
53 
54 	const size_t	m_size;
55 	std::vector<T>	m_elements;
56 
57 	size_t			m_front;
58 	size_t			m_back;
59 
60 	Mutex			m_writeMutex;
61 	Mutex			m_readMutex;
62 
63 	Semaphore		m_fill;
64 	Semaphore		m_empty;
65 };
66 
67 // ThreadSafeRingBuffer implementation.
68 
69 template <typename T>
ThreadSafeRingBuffer(size_t size)70 ThreadSafeRingBuffer<T>::ThreadSafeRingBuffer (size_t size)
71 	: m_size		(size+1)
72 	, m_elements	(m_size)
73 	, m_front		(0)
74 	, m_back		(0)
75 	, m_fill		(0)
76 	, m_empty		((int)size)
77 {
78 	// Semaphores currently only support INT_MAX
79 	DE_ASSERT(size > 0 && size < 0x7fffffff);
80 }
81 
82 template <typename T>
pushFrontInternal(const T & elem)83 inline void ThreadSafeRingBuffer<T>::pushFrontInternal (const T& elem)
84 {
85 	m_elements[m_front] = elem;
86 	m_front = (m_front + 1) % m_size;
87 }
88 
89 template <typename T>
popBackInternal()90 inline T ThreadSafeRingBuffer<T>::popBackInternal ()
91 {
92 	const size_t ndx = m_back;
93 	m_back = (m_back + 1) % m_size;
94 	return m_elements[ndx];
95 }
96 
97 template <typename T>
pushFront(const T & elem)98 void ThreadSafeRingBuffer<T>::pushFront (const T& elem)
99 {
100 	m_writeMutex.lock();
101 	m_empty.decrement();
102 	pushFrontInternal(elem);
103 	m_fill.increment();
104 	m_writeMutex.unlock();
105 }
106 
107 template <typename T>
tryPushFront(const T & elem)108 bool ThreadSafeRingBuffer<T>::tryPushFront (const T& elem)
109 {
110 	if (!m_writeMutex.tryLock())
111 		return false;
112 
113 	const bool success = m_empty.tryDecrement();
114 
115 	if (success)
116 	{
117 		pushFrontInternal(elem);
118 		m_fill.increment();
119 	}
120 
121 	m_writeMutex.unlock();
122 	return success;
123 }
124 
125 template <typename T>
popBack()126 T ThreadSafeRingBuffer<T>::popBack ()
127 {
128 	m_readMutex.lock();
129 	m_fill.decrement();
130 	T elem = popBackInternal();
131 	m_empty.increment();
132 	m_readMutex.unlock();
133 	return elem;
134 }
135 
136 template <typename T>
tryPopBack(T & dst)137 bool ThreadSafeRingBuffer<T>::tryPopBack (T& dst)
138 {
139 	if (!m_readMutex.tryLock())
140 		return false;
141 
142 	bool success = m_fill.tryDecrement();
143 
144 	if (success)
145 	{
146 		dst = popBackInternal();
147 		m_empty.increment();
148 	}
149 
150 	m_readMutex.unlock();
151 
152 	return success;
153 }
154 
155 } // de
156 
157 #endif // _DETHREADSAFERINGBUFFER_HPP
158