PageRenderTime 20ms CodeModel.GetById 9ms app.highlight 9ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/llcommon/llthreadsafequeue.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 205 lines | 109 code | 40 blank | 56 comment | 3 complexity | 03c2d7ecb18958aed3344098c391189c MD5 | raw file
  1/** 
  2 * @file llthreadsafequeue.h
  3 * @brief Base classes for thread, mutex and condition handling.
  4 *
  5 * $LicenseInfo:firstyear=2004&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27#ifndef LL_LLTHREADSAFEQUEUE_H
 28#define LL_LLTHREADSAFEQUEUE_H
 29
 30
 31#include <string>
 32#include <stdexcept>
 33
 34
 35struct apr_pool_t; // From apr_pools.h
 36class LLThreadSafeQueueImplementation; // See below.
 37
 38
 39//
 40// A general queue exception.
 41//
 42class LL_COMMON_API LLThreadSafeQueueError:
 43public std::runtime_error
 44{
 45public:
 46	LLThreadSafeQueueError(std::string const & message):
 47	std::runtime_error(message)
 48	{
 49		; // No op.
 50	}
 51};
 52
 53
 54//
 55// An exception raised when blocking operations are interrupted.
 56//
 57class LL_COMMON_API LLThreadSafeQueueInterrupt:
 58	public LLThreadSafeQueueError
 59{
 60public:
 61	LLThreadSafeQueueInterrupt(void):
 62		LLThreadSafeQueueError("queue operation interrupted")
 63	{
 64		; // No op.
 65	}
 66};
 67
 68
 69struct apr_queue_t; // From apr_queue.h
 70
 71
 72//
 73// Implementation details. 
 74//
 75class LL_COMMON_API LLThreadSafeQueueImplementation
 76{
 77public:
 78	LLThreadSafeQueueImplementation(apr_pool_t * pool, unsigned int capacity);
 79	~LLThreadSafeQueueImplementation();
 80	void pushFront(void * element);
 81	bool tryPushFront(void * element);
 82	void * popBack(void);
 83	bool tryPopBack(void *& element);
 84	size_t size();
 85	
 86private:
 87	bool mOwnsPool;
 88	apr_pool_t * mPool;
 89	apr_queue_t * mQueue;
 90};
 91
 92
 93//
 94// Implements a thread safe FIFO.
 95//
 96template<typename ElementT>
 97class LLThreadSafeQueue
 98{
 99public:
100	typedef ElementT value_type;
101	
102	// If the pool is set to NULL one will be allocated and managed by this
103	// queue.
104	LLThreadSafeQueue(apr_pool_t * pool = 0, unsigned int capacity = 1024);
105	
106	// Add an element to the front of queue (will block if the queue has
107	// reached capacity).
108	//
109	// This call will raise an interrupt error if the queue is deleted while
110	// the caller is blocked.
111	void pushFront(ElementT const & element);
112	
113	// Try to add an element to the front ofqueue without blocking. Returns
114	// true only if the element was actually added.
115	bool tryPushFront(ElementT const & element);
116	
117	// Pop the element at the end of the queue (will block if the queue is
118	// empty).
119	//
120	// This call will raise an interrupt error if the queue is deleted while
121	// the caller is blocked.
122	ElementT popBack(void);
123	
124	// Pop an element from the end of the queue if there is one available.
125	// Returns true only if an element was popped.
126	bool tryPopBack(ElementT & element);
127	
128	// Returns the size of the queue.
129	size_t size();
130
131private:
132	LLThreadSafeQueueImplementation mImplementation;
133};
134
135
136
137// LLThreadSafeQueue
138//-----------------------------------------------------------------------------
139
140
141template<typename ElementT>
142LLThreadSafeQueue<ElementT>::LLThreadSafeQueue(apr_pool_t * pool, unsigned int capacity):
143	mImplementation(pool, capacity)
144{
145	; // No op.
146}
147
148
149template<typename ElementT>
150void LLThreadSafeQueue<ElementT>::pushFront(ElementT const & element)
151{
152	ElementT * elementCopy = new ElementT(element);
153	try {
154		mImplementation.pushFront(elementCopy);
155	} catch (LLThreadSafeQueueInterrupt) {
156		delete elementCopy;
157		throw;
158	}
159}
160
161
162template<typename ElementT>
163bool LLThreadSafeQueue<ElementT>::tryPushFront(ElementT const & element)
164{
165	ElementT * elementCopy = new ElementT(element);
166	bool result = mImplementation.tryPushFront(elementCopy);
167	if(!result) delete elementCopy;
168	return result;
169}
170
171
172template<typename ElementT>
173ElementT LLThreadSafeQueue<ElementT>::popBack(void)
174{
175	ElementT * element = reinterpret_cast<ElementT *> (mImplementation.popBack());
176	ElementT result(*element);
177	delete element;
178	return result;
179}
180
181
182template<typename ElementT>
183bool LLThreadSafeQueue<ElementT>::tryPopBack(ElementT & element)
184{
185	void * storedElement;
186	bool result = mImplementation.tryPopBack(storedElement);
187	if(result) {
188		ElementT * elementPtr = reinterpret_cast<ElementT *>(storedElement); 
189		element = *elementPtr;
190		delete elementPtr;
191	} else {
192		; // No op.
193	}
194	return result;
195}
196
197
198template<typename ElementT>
199size_t LLThreadSafeQueue<ElementT>::size(void)
200{
201	return mImplementation.size();
202}
203
204
205#endif