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