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 {
00032     template< class T>
00033     class ListLocked
00034     {
00035     public:
00036 
00037         typedef T value_t;
00038     private:
00039         struct Cont :  public boost::intrusive::list_base_hook<> {
00040             T data;
00041         };
00042         typedef boost::intrusive::list<Cont> BufferType;
00043         typedef std::stack<Cont*> StackType;
00044         typedef typename BufferType::iterator Iterator;
00045         typedef typename BufferType::const_iterator CIterator;
00046 
00047         BufferType mlist;
00048         StackType  mreserved;
00049         unsigned int required;
00050 
00051         mutable OS::MutexRecursive m;
00052     public:
00057         ListLocked(unsigned int lsize, unsigned int unused = 0 )
00058             :required(lsize)
00059         {
00060             for(unsigned int i=0; i <lsize; ++i)
00061                 mreserved.push(new Cont());
00062         }
00063 
00064         ~ListLocked() {
00065             this->clear();
00066             while( !mreserved.empty() ) {
00067                 delete mreserved.top();
00068                 mreserved.pop();
00069             }
00070         }
00071 
00072         size_t capacity() const
00073         {
00074             OS::MutexLock lock(m);
00075             return mreserved.size() + mlist.size();
00076         }
00077 
00078         size_t size() const
00079         {
00080             OS::MutexLock lock(m);
00081             return mlist.size();
00082         }
00083 
00084         bool empty() const
00085         {
00086             OS::MutexLock lock(m);
00087             return mlist.empty();
00088         }
00089 
00097         void grow(size_t items = 1) {
00098             OS::MutexLock lock(m);
00099             required += items;
00100             if (required > mreserved.size() + mlist.size() ) {
00101                 while ( mreserved.size() + mlist.size() < required * 2) {
00102                     mreserved.push( new Cont() );
00103                 }
00104             }
00105         }
00113         void shrink(size_t items = 1) {
00114             OS::MutexLock lock(m);
00115             required -= items;
00116         }
00117 
00124         void reserve(size_t lsize)
00125         {
00126             OS::MutexLock lock(m);
00127             while ( mreserved.size() + mlist.size() < lsize) {
00128                 mreserved.push( new Cont() );
00129             }
00130         }
00131 
00132         void clear()
00133         {
00134             OS::MutexLock lock(m);
00135             mlist.clear_and_dispose( boost::bind(&ListLocked::give_back, this, _1) );
00136         }
00137 
00143         bool append( value_t item )
00144         {
00145             OS::MutexLock lock(m);
00146             if ( mreserved.empty() )
00147                 return false;
00148             mlist.push_back( this->get_item(item) );
00149             return true;
00150         }
00151 
00155         value_t front() const
00156         {
00157             OS::MutexLock lock(m);
00158             return mlist.front().data;
00159         }
00160 
00164         value_t back() const
00165         {
00166             OS::MutexLock lock(m);
00167             return mlist.back().data;
00168         }
00169 
00175         size_t append(const std::vector<T>& items)
00176         {
00177             OS::MutexLock lock(m);
00178             unsigned int max = mreserved.size();
00179             typename std::vector<T>::const_iterator it = items.begin();
00180             for(; it != items.end() && max != 0; ++it, --max )
00181                 mlist.push_back( this->get_item(*it) );
00182             return it - items.begin();
00183         }
00184 
00185 
00191         bool erase( value_t item )
00192         {
00193             OS::MutexLock lock(m);
00194             mlist.remove_and_dispose_if( boost::bind(&ListLocked::is_item, this, item, _1), boost::bind(&ListLocked::give_back, this, _1) );
00195             return true;
00196         }
00197 
00204         template<class Function>
00205         void apply(Function func )
00206         {
00207             OS::MutexLock lock(m);
00208             // A free beer for the one that can express this with a for_each construct.
00209             for (Iterator it = mlist.begin(); it != mlist.end(); ++it)
00210                 func( it->data );
00211         }
00212 
00218         template<class Function>
00219         value_t find_if( Function func, value_t blank = value_t() )
00220         {
00221             OS::MutexLock lock(m);
00222             Iterator it = std::find_if(mlist.begin(), mlist.end(), boost::bind(func, boost::bind(&ListLocked::get_data, this,_1)));
00223             if (it != mlist.end() )
00224                 return it->data;
00225             return blank;
00226         }
00227     private:
00233         void give_back(Cont* cont)
00234         {
00235             mreserved.push( cont );
00236         }
00237 
00238         Cont& get_item(value_t item)
00239         {
00240             Cont* c = mreserved.top();
00241             mreserved.pop();
00242             c->data = item;
00243             return *c;
00244         }
00245 
00246         value_t& get_data(Cont& c)
00247         {
00248             return c.data;
00249         }
00250 
00258         bool is_item(value_t item, const Cont& cont)
00259         {
00260             return item == cont.data;
00261         }
00262     };
00263 
00264 }
00265 
00266 #endif
Generated on Thu Dec 23 13:22:38 2010 for Orocos Real-Time Toolkit by  doxygen 1.6.3