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 "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_NAMED("actionlib", "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_NAMED("actionlib", "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 if ( rhs.valid_ ) {
00125 it_ = rhs.it_;
00126 }
00127 handle_tracker_ = rhs.handle_tracker_;
00128 valid_ = rhs.valid_;
00129 return rhs;
00130 }
00131
00136 void reset()
00137 {
00138 valid_ = false;
00139 #ifndef _MSC_VER
00140
00141
00142 it_ = iterator();
00143 #endif
00144 handle_tracker_.reset();
00145 }
00146
00152 T& getElem()
00153 {
00154 assert(valid_);
00155 return *it_;
00156 }
00157
00161 bool operator==(const Handle& rhs) const
00162 {
00163 assert(valid_);
00164 assert(rhs.valid_);
00165 return (it_ == rhs.it_);
00166 }
00167
00168 friend class ManagedList;
00169
00170
00171 friend class iterator;
00172 private:
00173 Handle( const boost::shared_ptr<void>& handle_tracker, iterator it) :
00174 it_(it), handle_tracker_(handle_tracker), valid_(true)
00175 { }
00176
00177 iterator it_;
00178 boost::shared_ptr<void> handle_tracker_;
00179 bool valid_;
00180 };
00181
00182 ManagedList() { }
00183
00187 Handle add(const T& elem)
00188 {
00189 return add(elem, boost::bind(&ManagedList<T>::defaultDeleter, this, _1) );
00190 }
00191
00197 Handle add(const T& elem, CustomDeleter custom_deleter, const boost::shared_ptr<DestructionGuard>& guard)
00198 {
00199 TrackedElem tracked_t;
00200 tracked_t.elem = elem;
00201
00202 typename std::list<TrackedElem>::iterator list_it = list_.insert(list_.end(), tracked_t);
00203 iterator managed_it = iterator(list_it);
00204
00205 ElemDeleter deleter(managed_it, custom_deleter, guard);
00206 boost::shared_ptr<void> tracker( (void*) NULL, deleter);
00207
00208 list_it->handle_tracker_ = tracker;
00209
00210 return Handle(tracker, managed_it);
00211 }
00212
00216 void erase(iterator it)
00217 {
00218 list_.erase(it.it_);
00219 }
00220
00221 iterator end() { return iterator(list_.end()); }
00222 iterator begin() { return iterator(list_.begin()); }
00223
00224 private:
00225 void defaultDeleter(iterator it)
00226 {
00227 erase(it);
00228 }
00229 std::list<TrackedElem> list_;
00230 };
00231
00232
00233 template<class T>
00234 typename ManagedList<T>::Handle ManagedList<T>::iterator::createHandle()
00235 {
00236 if (it_->handle_tracker_.expired())
00237 ROS_ERROR_NAMED("actionlib", "Tried to create a handle to a list elem with refcount 0");
00238
00239 boost::shared_ptr<void> tracker = it_->handle_tracker_.lock();
00240
00241 return Handle(tracker, *this);
00242 }
00243
00244 }
00245
00246 #endif