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
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