00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #ifndef ACTIONLIB_MANAGED_LIST_H_
00036 #define ACTIONLIB_MANAGED_LIST_H_
00037
00038 #include "ros/console.h"
00039 #include <boost/thread.hpp>
00040 #include <boost/shared_ptr.hpp>
00041 #include <boost/weak_ptr.hpp>
00042 #include <list>
00043 #include <actionlib/destruction_guard.h>
00044
00045 namespace actionlib
00046 {
00047
00053 template <class T>
00054 class ManagedList
00055 {
00056 private:
00057 struct TrackedElem
00058 {
00059 T elem;
00060 boost::weak_ptr<void> handle_tracker_;
00061 };
00062
00063 public:
00064 class Handle;
00065
00066 class iterator
00067 {
00068 public:
00069 iterator() { }
00070 T& operator*() { return it_->elem; }
00071 T& operator->() { return it_->elem; }
00072 bool operator==(const iterator& rhs) const { return it_ == rhs.it_; }
00073 bool operator!=(const iterator& rhs) const { return !(*this == rhs); }
00074 void operator++() { it_++; }
00075 Handle createHandle();
00076 friend class ManagedList;
00077 private:
00078 iterator(typename std::list<TrackedElem>::iterator it) : it_(it) { }
00079 typename std::list<TrackedElem>::iterator it_;
00080 };
00081
00082 typedef typename boost::function< void(iterator)> CustomDeleter;
00083
00084 private:
00085 class ElemDeleter
00086 {
00087 public:
00088 ElemDeleter(iterator it, CustomDeleter deleter, const boost::shared_ptr<DestructionGuard>& guard) :
00089 it_(it), deleter_(deleter), guard_(guard)
00090 { }
00091
00092 void operator() (void* ptr)
00093 {
00094 DestructionGuard::ScopedProtector protector(*guard_);
00095 if (!protector.isProtected())
00096 {
00097 ROS_ERROR("ManagedList: The DestructionGuard associated with this list has already been destructed. You must delete all list handles before deleting the ManagedList");
00098 return;
00099 }
00100
00101 ROS_DEBUG("IN DELETER");
00102 if (deleter_)
00103 deleter_(it_);
00104 }
00105
00106 private:
00107 iterator it_;
00108 CustomDeleter deleter_;
00109 boost::shared_ptr<DestructionGuard> guard_;
00110 };
00111
00112 public:
00113
00114 class Handle
00115 {
00116 public:
00120 Handle() : it_(iterator()), handle_tracker_(boost::shared_ptr<void>()), valid_(false) { }
00121
00122 const Handle& operator=(const Handle& rhs)
00123 {
00124 it_ = rhs.it_;
00125 handle_tracker_ = rhs.handle_tracker_;
00126 valid_ = rhs.valid_;
00127 return rhs;
00128 }
00129
00134 void reset()
00135 {
00136 valid_ = false;
00137 it_ = iterator();
00138 handle_tracker_.reset();
00139 }
00140
00146 T& getElem()
00147 {
00148 assert(valid_);
00149 return *it_;
00150 }
00151
00155 bool operator==(const Handle& rhs)
00156 {
00157 return (it_ == rhs.it_);
00158 }
00159
00160 friend class ManagedList;
00161
00162
00163 friend class iterator;
00164 private:
00165 Handle( const boost::shared_ptr<void>& handle_tracker, iterator it) :
00166 it_(it), handle_tracker_(handle_tracker), valid_(true)
00167 { }
00168
00169 iterator it_;
00170 boost::shared_ptr<void> handle_tracker_;
00171 bool valid_;
00172 };
00173
00174 ManagedList() { }
00175
00179 Handle add(const T& elem)
00180 {
00181 return add(elem, boost::bind(&ManagedList<T>::defaultDeleter, this, _1) );
00182 }
00183
00189 Handle add(const T& elem, CustomDeleter custom_deleter, const boost::shared_ptr<DestructionGuard>& guard)
00190 {
00191 TrackedElem tracked_t;
00192 tracked_t.elem = elem;
00193
00194 typename std::list<TrackedElem>::iterator list_it = list_.insert(list_.end(), tracked_t);
00195 iterator managed_it = iterator(list_it);
00196
00197 ElemDeleter deleter(managed_it, custom_deleter, guard);
00198 boost::shared_ptr<void> tracker( (void*) NULL, deleter);
00199
00200 list_it->handle_tracker_ = tracker;
00201
00202 return Handle(tracker, managed_it);
00203 }
00204
00208 void erase(iterator it)
00209 {
00210 list_.erase(it.it_);
00211 }
00212
00213 iterator end() { return iterator(list_.end()); }
00214 iterator begin() { return iterator(list_.begin()); }
00215
00216 private:
00217 void defaultDeleter(iterator it)
00218 {
00219 erase(it);
00220 }
00221 std::list<TrackedElem> list_;
00222 };
00223
00224
00225 template<class T>
00226 typename ManagedList<T>::Handle ManagedList<T>::iterator::createHandle()
00227 {
00228 if (it_->handle_tracker_.expired())
00229 ROS_ERROR("Tried to create a handle to a list elem with refcount 0");
00230
00231 boost::shared_ptr<void> tracker = it_->handle_tracker_.lock();
00232
00233 return Handle(tracker, *this);
00234 }
00235
00236 }
00237
00238 #endif