|
Equalizer
1.3.1-git
|
00001 00002 /* Copyright (c) 2005-2012, 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 LUNCHBOX_MTQUEUE_H 00019 #define LUNCHBOX_MTQUEUE_H 00020 00021 #include <lunchbox/condition.h> 00022 #include <lunchbox/debug.h> 00023 00024 #include <algorithm> 00025 #include <limits.h> 00026 #include <queue> 00027 #include <string.h> 00028 00029 namespace lunchbox 00030 { 00040 template< typename T, size_t S = ULONG_MAX > class MTQueue 00041 // S = std::numeric_limits< size_t >::max() does not work: 00042 // http://gcc.gnu.org/bugzilla/show_bug.cgi?id=6424 00043 { 00044 public: 00046 MTQueue( size_t maxSize = S ) : _maxSize( maxSize ) {} 00047 00049 MTQueue( const MTQueue< T, S >& from ) { *this = from; } 00050 00052 ~MTQueue() {} 00053 00055 MTQueue< T, S >& operator = ( const MTQueue< T, S >& from ) 00056 { 00057 if( this != &from ) 00058 { 00059 from._cond.lock(); 00060 std::deque< T > copy = from._queue; 00061 const size_t maxSize = from._maxSize; 00062 from._cond.unlock(); 00063 00064 _cond.lock(); 00065 _maxSize = maxSize; 00066 _queue.swap( copy ); 00067 _cond.signal(); 00068 _cond.unlock(); 00069 } 00070 return *this; 00071 } 00072 00077 const T& operator[]( const size_t index ) const 00078 { 00079 _cond.lock(); 00080 while( _queue.size() < index ) 00081 _cond.wait(); 00082 00083 LBASSERT( _queue.size() >= index ); 00084 const T& element = _queue[index]; 00085 _cond.unlock(); 00086 return element; 00087 } 00088 00090 bool isEmpty() const { return _queue.empty(); } 00091 00093 size_t getSize() const { return _queue.size(); } 00094 00103 void setMaxSize( const size_t maxSize ) 00104 { 00105 _cond.lock(); 00106 while( _queue.size() > maxSize ) 00107 _cond.wait(); 00108 _maxSize = maxSize; 00109 _cond.signal(); 00110 _cond.unlock(); 00111 } 00112 00114 size_t getMaxSize() const { return _maxSize; } 00115 00122 size_t waitSize( const size_t minSize ) const 00123 { 00124 LBASSERT( minSize <= _maxSize ); 00125 _cond.lock(); 00126 while( _queue.size() < minSize ) 00127 _cond.wait(); 00128 const size_t size = _queue.size(); 00129 _cond.unlock(); 00130 return size; 00131 } 00132 00134 void clear() 00135 { 00136 _cond.lock(); 00137 _queue.clear(); 00138 _cond.unlock(); 00139 } 00140 00145 T pop() 00146 { 00147 _cond.lock(); 00148 while( _queue.empty( )) 00149 _cond.wait(); 00150 00151 LBASSERT( !_queue.empty( )); 00152 T element = _queue.front(); 00153 _queue.pop_front(); 00154 _cond.signal(); 00155 _cond.unlock(); 00156 return element; 00157 } 00158 00168 bool timedPop( const unsigned timeout, T& element ) 00169 { 00170 _cond.lock(); 00171 while( _queue.empty( )) 00172 { 00173 if( !_cond.timedWait( timeout )) 00174 { 00175 _cond.unlock(); 00176 return false; 00177 } 00178 } 00179 LBASSERT( !_queue.empty( )); 00180 element = _queue.front(); 00181 _queue.pop_front(); 00182 _cond.signal(); 00183 _cond.unlock(); 00184 return true; 00185 } 00186 00195 bool tryPop( T& result ) 00196 { 00197 _cond.lock(); 00198 if( _queue.empty( )) 00199 { 00200 _cond.unlock(); 00201 return false; 00202 } 00203 00204 result = _queue.front(); 00205 _queue.pop_front(); 00206 _cond.signal(); 00207 _cond.unlock(); 00208 return true; 00209 } 00210 00223 void tryPop( const size_t num, std::vector< T >& result ) 00224 { 00225 _cond.lock(); 00226 const size_t size = LB_MIN( num, _queue.size( )); 00227 if( size > 0 ) 00228 { 00229 result.reserve( result.size() + size ); 00230 for( size_t i = 0; i < size; ++i ) 00231 { 00232 result.push_back( _queue.front( )); 00233 _queue.pop_front(); 00234 } 00235 _cond.signal(); 00236 } 00237 _cond.unlock(); 00238 } 00239 00246 bool getFront( T& result ) const 00247 { 00248 _cond.lock(); 00249 if( _queue.empty( )) 00250 { 00251 _cond.unlock(); 00252 return false; 00253 } 00254 // else 00255 result = _queue.front(); 00256 _cond.unlock(); 00257 return true; 00258 } 00259 00266 bool getBack( T& result ) const 00267 { 00268 _cond.lock(); 00269 if( _queue.empty( )) 00270 { 00271 _cond.unlock(); 00272 return false; 00273 } 00274 // else 00275 result = _queue.back(); 00276 _cond.unlock(); 00277 return true; 00278 } 00279 00281 void push( const T& element ) 00282 { 00283 _cond.lock(); 00284 while( _queue.size() >= _maxSize ) 00285 _cond.wait(); 00286 _queue.push_back( element ); 00287 _cond.signal(); 00288 _cond.unlock(); 00289 } 00290 00292 void push( const std::vector< T >& elements ) 00293 { 00294 _cond.lock(); 00295 LBASSERT( elements.size() <= _maxSize ); 00296 while( (_maxSize - _queue.size( )) < elements.size( )) 00297 _cond.wait(); 00298 _queue.insert( _queue.end(), elements.begin(), elements.end( )); 00299 _cond.signal(); 00300 _cond.unlock(); 00301 } 00302 00304 void pushFront( const T& element ) 00305 { 00306 _cond.lock(); 00307 while( _queue.size() >= _maxSize ) 00308 _cond.wait(); 00309 _queue.push_front( element ); 00310 _cond.signal(); 00311 _cond.unlock(); 00312 } 00313 00315 void pushFront( const std::vector< T >& elements ) 00316 { 00317 _cond.lock(); 00318 LBASSERT( elements.size() <= _maxSize ); 00319 while( (_maxSize - _queue.size( )) < elements.size( )) 00320 _cond.wait(); 00321 _queue.insert(_queue.begin(), elements.begin(), elements.end()); 00322 _cond.signal(); 00323 _cond.unlock(); 00324 } 00325 00326 00327 private: 00328 std::deque< T > _queue; 00329 mutable Condition _cond; 00330 size_t _maxSize; 00331 }; 00332 } 00333 #endif //LUNCHBOX_MTQUEUE_H
1.3.1-git by
1.8.0