Equalizer  1.2.1
mtQueue.h
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
Generated on Fri Jun 8 2012 15:44:31 for Equalizer 1.2.1 by  doxygen 1.8.0