Equalizer
1.2.1
|
00001 00002 /* Copyright (c) 2005-2011, Stefan Eilemann <eile@equalizergraphics.com> 00003 * 00004 * This library is free software; you can redistribute it and/or modify it under 00005 * the terms of the GNU Lesser General Public License version 2.1 as published 00006 * by the Free Software Foundation. 00007 * 00008 * This library is distributed in the hope that it will be useful, but WITHOUT 00009 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00010 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 00011 * details. 00012 * 00013 * You should have received a copy of the GNU Lesser General Public License 00014 * along with this library; if not, write to the Free Software Foundation, Inc., 00015 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00016 */ 00017 00018 #ifndef COBASE_MTQUEUE_H 00019 #define COBASE_MTQUEUE_H 00020 00021 #include <co/base/condition.h> 00022 #include <co/base/debug.h> 00023 00024 #include <algorithm> 00025 #include <limits.h> 00026 #include <queue> 00027 #include <string.h> 00028 00029 namespace co 00030 { 00031 namespace base 00032 { 00041 template< typename T, size_t S = ULONG_MAX > class MTQueue 00042 // S = std::numeric_limits< size_t >::max() does not work: 00043 // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=6424 00044 { 00045 public: 00047 MTQueue() {} 00048 00050 MTQueue( const MTQueue< T, S >& from ) : _queue( from._queue ) {} 00051 00053 ~MTQueue() {} 00054 00056 MTQueue< T, S >& operator = ( const MTQueue< T, S >& from ) 00057 { 00058 _cond.lock(); 00059 _queue = from._queue; 00060 _cond.signal(); 00061 _cond.unlock(); 00062 return *this; 00063 } 00064 00066 bool isEmpty() const { return _queue.empty(); } 00067 00069 size_t getSize() const { return _queue.size(); } 00070 00077 size_t waitSize( const size_t minSize ) const 00078 { 00079 EQASSERT( minSize <= S ); 00080 _cond.lock(); 00081 while( _queue.size() < minSize ) 00082 _cond.wait(); 00083 const size_t size = _queue.size(); 00084 _cond.unlock(); 00085 return size; 00086 } 00087 00089 void clear() 00090 { 00091 _cond.lock(); 00092 _queue.clear(); 00093 _cond.unlock(); 00094 } 00095 00100 T pop() 00101 { 00102 _cond.lock(); 00103 while( _queue.empty( )) 00104 _cond.wait(); 00105 00106 EQASSERT( !_queue.empty( )); 00107 T element = _queue.front(); 00108 _queue.pop_front(); 00109 _cond.signal(); 00110 _cond.unlock(); 00111 return element; 00112 } 00113 00123 bool timedPop( const unsigned timeout, T& element ) 00124 { 00125 _cond.lock(); 00126 while( _queue.empty( )) 00127 { 00128 if( !_cond.timedWait( timeout )) 00129 { 00130 _cond.unlock(); 00131 return false; 00132 } 00133 } 00134 EQASSERT( !_queue.empty( )); 00135 element = _queue.front(); 00136 _queue.pop_front(); 00137 _cond.signal(); 00138 _cond.unlock(); 00139 return true; 00140 } 00141 00150 bool tryPop( T& result ) 00151 { 00152 _cond.lock(); 00153 if( _queue.empty( )) 00154 { 00155 _cond.unlock(); 00156 return false; 00157 } 00158 00159 result = _queue.front(); 00160 _queue.pop_front(); 00161 _cond.signal(); 00162 _cond.unlock(); 00163 return true; 00164 } 00165 00178 void tryPop( const size_t num, std::vector< T >& result ) 00179 { 00180 _cond.lock(); 00181 const size_t size = EQ_MIN( num, _queue.size( )); 00182 if( size > 0 ) 00183 { 00184 result.reserve( result.size() + size ); 00185 for( size_t i = 0; i < size; ++i ) 00186 { 00187 result.push_back( _queue.front( )); 00188 _queue.pop_front(); 00189 } 00190 _cond.signal(); 00191 } 00192 _cond.unlock(); 00193 } 00194 00201 bool getFront( T& result ) const 00202 { 00203 _cond.lock(); 00204 if( _queue.empty( )) 00205 { 00206 _cond.unlock(); 00207 return false; 00208 } 00209 // else 00210 result = _queue.front(); 00211 _cond.unlock(); 00212 return true; 00213 } 00214 00221 bool getBack( T& result ) const 00222 { 00223 _cond.lock(); 00224 if( _queue.empty( )) 00225 { 00226 _cond.unlock(); 00227 return false; 00228 } 00229 // else 00230 result = _queue.back(); 00231 _cond.unlock(); 00232 return true; 00233 } 00234 00236 void push( const T& element ) 00237 { 00238 _cond.lock(); 00239 while( _queue.size() >= S ) 00240 _cond.wait(); 00241 _queue.push_back( element ); 00242 _cond.signal(); 00243 _cond.unlock(); 00244 } 00245 00247 void push( const std::vector< T >& elements ) 00248 { 00249 _cond.lock(); 00250 EQASSERT( elements.size() <= S ); 00251 while( (S - _queue.size( )) < elements.size( )) 00252 _cond.wait(); 00253 _queue.insert( _queue.end(), elements.begin(), elements.end( )); 00254 _cond.signal(); 00255 _cond.unlock(); 00256 } 00257 00259 void pushFront( const T& element ) 00260 { 00261 _cond.lock(); 00262 while(_queue.size() >= S) 00263 _cond.wait(); 00264 _queue.push_front( element ); 00265 _cond.signal(); 00266 _cond.unlock(); 00267 } 00268 00270 void pushFront( const std::vector< T >& elements ) 00271 { 00272 _cond.lock(); 00273 EQASSERT( elements.size() <= S ); 00274 while( (S - _queue.size( )) < elements.size( )) 00275 _cond.wait(); 00276 _queue.insert(_queue.begin(), elements.begin(), elements.end()); 00277 _cond.signal(); 00278 _cond.unlock(); 00279 } 00280 00281 00282 private: 00283 std::deque< T > _queue; 00284 mutable Condition _cond; 00285 }; 00286 } 00287 } 00288 #endif //COBASE_MTQUEUE_H