ListLocked.hpp

00001 
00002 #ifndef ORO_LIST_LOCKED_HPP
00003 #define ORO_LIST_LOCKED_HPP
00004 
00005 #include <boost/intrusive/list.hpp>
00006 #include <boost/bind.hpp>
00007 #include <boost/bind/protect.hpp>
00008 #include <stack>
00009 #include <vector>
00010 #include <algorithm>
00011 #include "os/Mutex.hpp"
00012 #include "os/MutexLock.hpp"
00013 
00014 #ifdef ORO_PRAGMA_INTERFACE
00015 #pragma interface
00016 #endif
00017 
00018 namespace RTT
00019 {
00028     template< class T>
00029     class ListLocked
00030     {
00031     public:
00032 
00033         typedef T value_t;
00034     private:
00035         struct Cont :  public boost::intrusive::list_base_hook<> {
00036             T data;
00037         };
00038         typedef boost::intrusive::list<Cont> BufferType;
00039         typedef std::stack<Cont*> StackType;
00040         typedef typename BufferType::iterator Iterator;
00041         typedef typename BufferType::const_iterator CIterator;
00042 
00043         BufferType mlist;
00044         StackType  mreserved;
00045         unsigned int required;
00046 
00047         mutable OS::Mutex m;
00048     public:
00053         ListLocked(unsigned int lsize, unsigned int unused = 0 )
00054             :required(lsize)
00055         {
00056             for(unsigned int i=0; i <lsize; ++i)
00057                 mreserved.push(new Cont());
00058         }
00059 
00060         ~ListLocked() {
00061             this->clear();
00062             while( !mreserved.empty() ) {
00063                 delete mreserved.top();
00064                 mreserved.pop();
00065             }
00066         }
00067 
00068         size_t capacity() const
00069         {
00070             OS::MutexLock lock(m);
00071             return mreserved.size() + mlist.size();
00072         }
00073 
00074         size_t size() const
00075         {
00076             OS::MutexLock lock(m);
00077             return mlist.size();
00078         }
00079 
00080         bool empty() const
00081         {
00082             OS::MutexLock lock(m);
00083             return mlist.empty();
00084         }
00085 
00093         void grow(size_t items = 1) {
00094             OS::MutexLock lock(m);
00095             required += items;
00096             if (required > mreserved.size() + mlist.size() ) {
00097                 while ( mreserved.size() + mlist.size() < required * 2) {
00098                     mreserved.push( new Cont() );
00099                 }
00100             }
00101         }
00109         void shrink(size_t items = 1) {
00110             OS::MutexLock lock(m);
00111             required -= items;
00112         }
00113 
00120         void reserve(size_t lsize)
00121         {
00122             OS::MutexLock lock(m);
00123             while ( mreserved.size() + mlist.size() < lsize) {
00124                 mreserved.push( new Cont() );
00125             }
00126         }
00127 
00128         void clear()
00129         {
00130             OS::MutexLock lock(m);
00131             mlist.clear_and_dispose( boost::bind(&ListLocked::give_back, this, _1) );
00132         }
00133 
00139         bool append( value_t item )
00140         {
00141             OS::MutexLock lock(m);
00142             if ( mreserved.empty() )
00143                 return false;
00144             mlist.push_back( this->get_item(item) );
00145             return true;
00146         }
00147 
00151         value_t front() const
00152         {
00153             OS::MutexLock lock(m);
00154             return mlist.front().data;
00155         }
00156 
00160         value_t back() const
00161         {
00162             OS::MutexLock lock(m);
00163             return mlist.back().data;
00164         }
00165 
00171         size_t append(const std::vector<T>& items)
00172         {
00173             OS::MutexLock lock(m);
00174             unsigned int max = mreserved.size();
00175             typename std::vector<T>::const_iterator it = items.begin();
00176             for(; it != items.end() && max != 0; ++it, --max )
00177                 mlist.push_back( this->get_item(*it) );
00178             return it - items.begin();
00179         }
00180 
00181 
00187         bool erase( value_t item )
00188         {
00189             OS::MutexLock lock(m);
00190             mlist.remove_and_dispose_if( boost::bind(&ListLocked::is_item, this, item, _1), boost::bind(&ListLocked::give_back, this, _1) );
00191             return true;
00192         }
00193 
00198         template<class Function>
00199         void apply(Function func )
00200         {
00201             OS::MutexLock lock(m);
00202             // A free beer for the one that can express this with a for_each construct.
00203             for (Iterator it = mlist.begin(); it != mlist.end(); ++it)
00204                 func( it->data );
00205         }
00206 
00212         template<class Function>
00213         value_t find_if( Function func, value_t blank = value_t() )
00214         {
00215             OS::MutexLock lock(m);
00216             Iterator it = std::find_if(mlist.begin(), mlist.end(), boost::bind(func, boost::bind(&ListLocked::get_data, this,_1)));
00217             if (it != mlist.end() )
00218                 return it->data;
00219             return blank;
00220         }
00221     private:
00227         void give_back(Cont* cont)
00228         {
00229             mreserved.push( cont );
00230         }
00231 
00232         Cont& get_item(value_t item)
00233         {
00234             Cont* c = mreserved.top();
00235             mreserved.pop();
00236             c->data = item;
00237             return *c;
00238         }
00239 
00240         value_t& get_data(Cont& c)
00241         {
00242             return c.data;
00243         }
00244 
00252         bool is_item(value_t item, const Cont& cont)
00253         {
00254             return item == cont.data;
00255         }
00256     };
00257 
00258 }
00259 
00260 #endif

Generated on Tue Jul 13 11:03:23 2010 for Orocos Real-Time Toolkit by  doxygen 1.6.1