Orocos Real-Time Toolkit
2.5.0
|
00001 /*************************************************************************** 00002 tag: Peter Soetens Thu Oct 22 11:59:08 CEST 2009 ListLocked.hpp 00003 00004 ListLocked.hpp - description 00005 ------------------- 00006 begin : Thu October 22 2009 00007 copyright : (C) 2009 Peter Soetens 00008 email : peter@thesourcworks.com 00009 00010 *************************************************************************** 00011 * This library is free software; you can redistribute it and/or * 00012 * modify it under the terms of the GNU General Public * 00013 * License as published by the Free Software Foundation; * 00014 * version 2 of the License. * 00015 * * 00016 * As a special exception, you may use this file as part of a free * 00017 * software library without restriction. Specifically, if other files * 00018 * instantiate templates or use macros or inline functions from this * 00019 * file, or you compile this file and link it with other files to * 00020 * produce an executable, this file does not by itself cause the * 00021 * resulting executable to be covered by the GNU General Public * 00022 * License. This exception does not however invalidate any other * 00023 * reasons why the executable file might be covered by the GNU General * 00024 * Public License. * 00025 * * 00026 * This library is distributed in the hope that it will be useful, * 00027 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00028 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * 00029 * Lesser General Public License for more details. * 00030 * * 00031 * You should have received a copy of the GNU General Public * 00032 * License along with this library; if not, write to the Free Software * 00033 * Foundation, Inc., 59 Temple Place, * 00034 * Suite 330, Boston, MA 02111-1307 USA * 00035 * * 00036 ***************************************************************************/ 00037 00038 00039 00040 #ifndef ORO_LIST_LOCKED_HPP 00041 #define ORO_LIST_LOCKED_HPP 00042 00043 #include <boost/intrusive/list.hpp> 00044 #include <boost/bind.hpp> 00045 #include <boost/bind/protect.hpp> 00046 #include <stack> 00047 #include <vector> 00048 #include <algorithm> 00049 #include "../os/Mutex.hpp" 00050 #include "../os/MutexLock.hpp" 00051 00052 #ifdef ORO_PRAGMA_INTERFACE 00053 #pragma interface 00054 #endif 00055 00056 namespace RTT 00057 { namespace internal { 00058 00071 template< class T> 00072 class ListLocked 00073 { 00074 public: 00075 00076 typedef T value_t; 00077 private: 00078 struct Cont : public boost::intrusive::list_base_hook<> { 00079 T data; 00080 }; 00081 typedef boost::intrusive::list<Cont> BufferType; 00082 typedef std::stack<Cont*> StackType; 00083 typedef typename BufferType::iterator Iterator; 00084 typedef typename BufferType::const_iterator CIterator; 00085 00086 BufferType mlist; 00087 StackType mreserved; 00088 unsigned int required; 00089 00090 mutable os::MutexRecursive m; 00091 public: 00096 ListLocked(unsigned int lsize, unsigned int unused = 0 ) 00097 :required(lsize) 00098 { 00099 for(unsigned int i=0; i <lsize; ++i) 00100 mreserved.push(new Cont()); 00101 } 00102 00103 ~ListLocked() { 00104 this->clear(); 00105 while( !mreserved.empty() ) { 00106 delete mreserved.top(); 00107 mreserved.pop(); 00108 } 00109 } 00110 00111 size_t capacity() const 00112 { 00113 os::MutexLock lock(m); 00114 return mreserved.size() + mlist.size(); 00115 } 00116 00117 size_t size() const 00118 { 00119 os::MutexLock lock(m); 00120 return mlist.size(); 00121 } 00122 00123 bool empty() const 00124 { 00125 os::MutexLock lock(m); 00126 return mlist.empty(); 00127 } 00128 00136 void grow(size_t items = 1) { 00137 os::MutexLock lock(m); 00138 required += items; 00139 if (required > mreserved.size() + mlist.size() ) { 00140 while ( mreserved.size() + mlist.size() < required * 2) { 00141 mreserved.push( new Cont() ); 00142 } 00143 } 00144 } 00152 void shrink(size_t items = 1) { 00153 os::MutexLock lock(m); 00154 required -= items; 00155 } 00156 00163 void reserve(size_t lsize) 00164 { 00165 os::MutexLock lock(m); 00166 while ( mreserved.size() + mlist.size() < lsize) { 00167 mreserved.push( new Cont() ); 00168 } 00169 } 00170 00171 void clear() 00172 { 00173 os::MutexLock lock(m); 00174 mlist.clear_and_dispose( boost::bind(&ListLocked::give_back, this, _1) ); 00175 } 00176 00182 bool append( value_t item ) 00183 { 00184 os::MutexLock lock(m); 00185 if ( mreserved.empty() ) 00186 return false; 00187 mlist.push_back( this->get_item(item) ); 00188 return true; 00189 } 00190 00194 value_t front() const 00195 { 00196 os::MutexLock lock(m); 00197 return mlist.front().data; 00198 } 00199 00203 value_t back() const 00204 { 00205 os::MutexLock lock(m); 00206 return mlist.back().data; 00207 } 00208 00214 size_t append(const std::vector<T>& items) 00215 { 00216 os::MutexLock lock(m); 00217 unsigned int max = mreserved.size(); 00218 typename std::vector<T>::const_iterator it = items.begin(); 00219 for(; it != items.end() && max != 0; ++it, --max ) 00220 mlist.push_back( this->get_item(*it) ); 00221 return it - items.begin(); 00222 } 00223 00224 00230 bool erase( value_t item ) 00231 { 00232 os::MutexLock lock(m); 00233 mlist.remove_and_dispose_if( boost::bind(&ListLocked::is_item, this, item, _1), boost::bind(&ListLocked::give_back, this, _1) ); 00234 return true; 00235 } 00236 00244 template<typename Pred> 00245 bool delete_if(Pred pred) 00246 { 00247 os::MutexLock lock(m); 00248 bool deleted = false; 00249 00250 typename BufferType::iterator cur(mlist.begin()); 00251 typename BufferType::iterator last(mlist.end()); 00252 00253 while(cur != last) 00254 { 00255 if(pred(cur->data)) 00256 { 00257 cur = mlist.erase_and_dispose(cur, boost::bind(&ListLocked::give_back, this, ::_1) ); 00258 deleted = true; 00259 } 00260 else 00261 ++cur; 00262 } 00263 00264 return deleted; 00265 } 00266 00273 template<class Function> 00274 void apply(Function func ) 00275 { 00276 os::MutexLock lock(m); 00277 // A free beer for the one that can express this with a for_each construct. 00278 for (Iterator it = mlist.begin(); it != mlist.end(); ++it) 00279 func( it->data ); 00280 } 00281 00287 template<class Function> 00288 value_t find_if( Function func, value_t blank = value_t() ) 00289 { 00290 os::MutexLock lock(m); 00291 Iterator it = std::find_if(mlist.begin(), mlist.end(), boost::bind(func, boost::bind(&ListLocked::get_data, this,_1))); 00292 if (it != mlist.end() ) 00293 return it->data; 00294 return blank; 00295 } 00296 private: 00302 void give_back(Cont* cont) 00303 { 00304 mreserved.push( cont ); 00305 } 00306 00307 Cont& get_item(value_t item) 00308 { 00309 Cont* c = mreserved.top(); 00310 mreserved.pop(); 00311 c->data = item; 00312 return *c; 00313 } 00314 00315 value_t& get_data(Cont& c) 00316 { 00317 return c.data; 00318 } 00319 00327 bool is_item(value_t item, const Cont& cont) 00328 { 00329 return item == cont.data; 00330 } 00331 }; 00332 00333 }} 00334 00335 #endif