Go to the documentation of this file.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 <actionlib/destruction_guard.h>
00039 #include <boost/thread.hpp>
00040 #include <boost/shared_ptr.hpp>
00041 #include <boost/weak_ptr.hpp>
00042
00043 #include <list>
00044
00045 #include "ros/console.h"
00046
00047 namespace actionlib
00048 {
00049
00055 template<class T>
00056 class ManagedList
00057 {
00058 private:
00059 struct TrackedElem
00060 {
00061 T elem;
00062 boost::weak_ptr<void> handle_tracker_;
00063 };
00064
00065 public:
00066 class Handle;
00067
00068 class iterator
00069 {
00070 public:
00071 iterator() {}
00072 T & operator*() {return it_->elem; }
00073 T & operator->() {return it_->elem; }
00074 const T & operator*() const {return it_->elem; }
00075 const T & operator->() const {return it_->elem; }
00076 bool operator==(const iterator & rhs) const {return it_ == rhs.it_; }
00077 bool operator!=(const iterator & rhs) const {return !(*this == rhs); }
00078 void operator++() {it_++; }
00079 Handle createHandle();
00080 friend class ManagedList;
00081
00082 private:
00083 iterator(typename std::list<TrackedElem>::iterator it)
00084 : it_(it) {}
00085 typename std::list<TrackedElem>::iterator it_;
00086 };
00087
00088 typedef typename boost::function<void (iterator)> CustomDeleter;
00089
00090 private:
00091 class ElemDeleter
00092 {
00093 public:
00094 ElemDeleter(iterator it, CustomDeleter deleter,
00095 const boost::shared_ptr<DestructionGuard> & guard)
00096 : it_(it), deleter_(deleter), guard_(guard)
00097 {}
00098
00099 void operator()(void *)
00100 {
00101 DestructionGuard::ScopedProtector protector(*guard_);
00102 if (!protector.isProtected()) {
00103 ROS_ERROR_NAMED("actionlib",
00104 "ManagedList: The DestructionGuard associated with this list has already been destructed. You must delete all list handles before deleting the ManagedList");
00105 return;
00106 }
00107
00108 ROS_DEBUG_NAMED("actionlib", "IN DELETER");
00109 if (deleter_) {
00110 deleter_(it_);
00111 }
00112 }
00113
00114 private:
00115 iterator it_;
00116 CustomDeleter deleter_;
00117 boost::shared_ptr<DestructionGuard> guard_;
00118 };
00119
00120 public:
00121 class Handle
00122 {
00123 public:
00127 Handle()
00128 : it_(iterator()), handle_tracker_(boost::shared_ptr<void>()), valid_(false) {}
00129
00130 Handle & operator=(const Handle & rhs)
00131 {
00132 if (rhs.valid_) {
00133 it_ = rhs.it_;
00134 }
00135 handle_tracker_ = rhs.handle_tracker_;
00136 valid_ = rhs.valid_;
00137 return *this;
00138 }
00139
00144 void reset()
00145 {
00146 valid_ = false;
00147 #ifndef _MSC_VER
00148
00149
00150 it_ = iterator();
00151 #endif
00152 handle_tracker_.reset();
00153 }
00154
00160 T & getElem()
00161 {
00162 assert(valid_);
00163 return *it_;
00164 }
00165
00166 const T & getElem() const
00167 {
00168 assert(valid_);
00169 return *it_;
00170 }
00171
00175 bool operator==(const Handle & rhs) const
00176 {
00177 assert(valid_);
00178 assert(rhs.valid_);
00179 return it_ == rhs.it_;
00180 }
00181
00182 friend class ManagedList;
00183
00184
00185 friend class iterator;
00186
00187 private:
00188 Handle(const boost::shared_ptr<void> & handle_tracker, iterator it)
00189 : it_(it), handle_tracker_(handle_tracker), valid_(true)
00190 {}
00191
00192 iterator it_;
00193 boost::shared_ptr<void> handle_tracker_;
00194 bool valid_;
00195 };
00196
00197 ManagedList() {}
00198
00202 Handle add(const T & elem)
00203 {
00204 return add(elem, boost::bind(&ManagedList<T>::defaultDeleter, this, _1) );
00205 }
00206
00212 Handle add(const T & elem, CustomDeleter custom_deleter,
00213 const boost::shared_ptr<DestructionGuard> & guard)
00214 {
00215 TrackedElem tracked_t;
00216 tracked_t.elem = elem;
00217
00218 typename std::list<TrackedElem>::iterator list_it = list_.insert(list_.end(), tracked_t);
00219 iterator managed_it = iterator(list_it);
00220
00221 ElemDeleter deleter(managed_it, custom_deleter, guard);
00222 boost::shared_ptr<void> tracker( (void *) NULL, deleter);
00223
00224 list_it->handle_tracker_ = tracker;
00225
00226 return Handle(tracker, managed_it);
00227 }
00228
00232 void erase(iterator it)
00233 {
00234 list_.erase(it.it_);
00235 }
00236
00237 iterator end() {return iterator(list_.end()); }
00238 iterator begin() {return iterator(list_.begin()); }
00239
00240 private:
00241 void defaultDeleter(iterator it)
00242 {
00243 erase(it);
00244 }
00245 std::list<TrackedElem> list_;
00246 };
00247
00248
00249 template<class T>
00250 typename ManagedList<T>::Handle ManagedList<T>::iterator::createHandle() {
00251 if (it_->handle_tracker_.expired()) {
00252 ROS_ERROR_NAMED("actionlib", "Tried to create a handle to a list elem with refcount 0");
00253 }
00254
00255 boost::shared_ptr<void> tracker = it_->handle_tracker_.lock();
00256
00257 return Handle(tracker, *this);
00258 }
00259
00260 }
00261
00262 #endif // ACTIONLIB__MANAGED_LIST_H_