Lunchbox
1.6.0
|
00001 00002 /* Copyright (c) 2005-2012, Stefan Eilemann <eile@equalizergraphics.com> 00003 * 2012, Daniel Nachbaur <danielnachbaur@gmail.com> 00004 * 00005 * This library is free software; you can redistribute it and/or modify it under 00006 * the terms of the GNU Lesser General Public License version 2.1 as published 00007 * by the Free Software Foundation. 00008 * 00009 * This library is distributed in the hope that it will be useful, but WITHOUT 00010 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 00011 * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more 00012 * details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public License 00015 * along with this library; if not, write to the Free Software Foundation, Inc., 00016 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 00017 */ 00018 00019 #ifndef LUNCHBOX_MTQUEUE_H 00020 #define LUNCHBOX_MTQUEUE_H 00021 00022 #include <lunchbox/condition.h> 00023 #include <lunchbox/debug.h> 00024 00025 #include <algorithm> 00026 #include <limits.h> 00027 #include <queue> 00028 #include <string.h> 00029 00030 namespace lunchbox 00031 { 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( size_t maxSize = S ) : _maxSize( maxSize ) {} 00048 00050 MTQueue( const MTQueue< T, S >& from ) { *this = from; } 00051 00053 ~MTQueue() {} 00054 00056 MTQueue< T, S >& operator = ( const MTQueue< T, S >& from ) 00057 { 00058 if( this != &from ) 00059 { 00060 from._cond.lock(); 00061 std::deque< T > copy = from._queue; 00062 const size_t maxSize = from._maxSize; 00063 from._cond.unlock(); 00064 00065 _cond.lock(); 00066 _maxSize = maxSize; 00067 _queue.swap( copy ); 00068 _cond.signal(); 00069 _cond.unlock(); 00070 } 00071 return *this; 00072 } 00073 00078 const T& operator[]( const size_t index ) const 00079 { 00080 _cond.lock(); 00081 while( _queue.size() <= index ) 00082 _cond.wait(); 00083 00084 LBASSERT( _queue.size() > index ); 00085 const T& element = _queue[index]; 00086 _cond.unlock(); 00087 return element; 00088 } 00089 00091 bool isEmpty() const { return _queue.empty(); } 00092 00094 size_t getSize() const { return _queue.size(); } 00095 00104 void setMaxSize( const size_t maxSize ) 00105 { 00106 _cond.lock(); 00107 while( _queue.size() > maxSize ) 00108 _cond.wait(); 00109 _maxSize = maxSize; 00110 _cond.signal(); 00111 _cond.unlock(); 00112 } 00113 00115 size_t getMaxSize() const { return _maxSize; } 00116 00123 size_t waitSize( const size_t minSize ) const 00124 { 00125 LBASSERT( minSize <= _maxSize ); 00126 _cond.lock(); 00127 while( _queue.size() < minSize ) 00128 _cond.wait(); 00129 const size_t size = _queue.size(); 00130 _cond.unlock(); 00131 return size; 00132 } 00133 00135 void clear() 00136 { 00137 _cond.lock(); 00138 _queue.clear(); 00139 _cond.signal(); 00140 _cond.unlock(); 00141 } 00142 00147 T pop() 00148 { 00149 _cond.lock(); 00150 while( _queue.empty( )) 00151 _cond.wait(); 00152 00153 LBASSERT( !_queue.empty( )); 00154 T element = _queue.front(); 00155 _queue.pop_front(); 00156 _cond.signal(); 00157 _cond.unlock(); 00158 return element; 00159 } 00160 00170 bool timedPop( const unsigned timeout, T& element ) 00171 { 00172 _cond.lock(); 00173 while( _queue.empty( )) 00174 { 00175 if( !_cond.timedWait( timeout )) 00176 { 00177 _cond.unlock(); 00178 return false; 00179 } 00180 } 00181 LBASSERT( !_queue.empty( )); 00182 element = _queue.front(); 00183 _queue.pop_front(); 00184 _cond.signal(); 00185 _cond.unlock(); 00186 return true; 00187 } 00188 00197 bool tryPop( T& result ) 00198 { 00199 _cond.lock(); 00200 if( _queue.empty( )) 00201 { 00202 _cond.unlock(); 00203 return false; 00204 } 00205 00206 result = _queue.front(); 00207 _queue.pop_front(); 00208 _cond.signal(); 00209 _cond.unlock(); 00210 return true; 00211 } 00212 00225 void tryPop( const size_t num, std::vector< T >& result ) 00226 { 00227 _cond.lock(); 00228 const size_t size = LB_MIN( num, _queue.size( )); 00229 if( size > 0 ) 00230 { 00231 result.reserve( result.size() + size ); 00232 for( size_t i = 0; i < size; ++i ) 00233 { 00234 result.push_back( _queue.front( )); 00235 _queue.pop_front(); 00236 } 00237 _cond.signal(); 00238 } 00239 _cond.unlock(); 00240 } 00241 00248 bool getFront( T& result ) const 00249 { 00250 _cond.lock(); 00251 if( _queue.empty( )) 00252 { 00253 _cond.unlock(); 00254 return false; 00255 } 00256 // else 00257 result = _queue.front(); 00258 _cond.unlock(); 00259 return true; 00260 } 00261 00268 bool getBack( T& result ) const 00269 { 00270 _cond.lock(); 00271 if( _queue.empty( )) 00272 { 00273 _cond.unlock(); 00274 return false; 00275 } 00276 // else 00277 result = _queue.back(); 00278 _cond.unlock(); 00279 return true; 00280 } 00281 00283 void push( const T& element ) 00284 { 00285 _cond.lock(); 00286 while( _queue.size() >= _maxSize ) 00287 _cond.wait(); 00288 _queue.push_back( element ); 00289 _cond.signal(); 00290 _cond.unlock(); 00291 } 00292 00294 void push( const std::vector< T >& elements ) 00295 { 00296 _cond.lock(); 00297 LBASSERT( elements.size() <= _maxSize ); 00298 while( (_maxSize - _queue.size( )) < elements.size( )) 00299 _cond.wait(); 00300 _queue.insert( _queue.end(), elements.begin(), elements.end( )); 00301 _cond.signal(); 00302 _cond.unlock(); 00303 } 00304 00306 void pushFront( const T& element ) 00307 { 00308 _cond.lock(); 00309 while( _queue.size() >= _maxSize ) 00310 _cond.wait(); 00311 _queue.push_front( element ); 00312 _cond.signal(); 00313 _cond.unlock(); 00314 } 00315 00317 void pushFront( const std::vector< T >& elements ) 00318 { 00319 _cond.lock(); 00320 LBASSERT( elements.size() <= _maxSize ); 00321 while( (_maxSize - _queue.size( )) < elements.size( )) 00322 _cond.wait(); 00323 _queue.insert(_queue.begin(), elements.begin(), elements.end()); 00324 _cond.signal(); 00325 _cond.unlock(); 00326 } 00327 00328 00329 private: 00330 std::deque< T > _queue; 00331 mutable Condition _cond; 00332 size_t _maxSize; 00333 }; 00334 } 00335 #endif //LUNCHBOX_MTQUEUE_H