Changeset 7327 for code/branches/doc/src/libraries/util/SharedPtr.h
- Timestamp:
- Sep 3, 2010, 12:19:53 AM (15 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
code/branches/doc/src/libraries/util/SharedPtr.h
r7284 r7327 27 27 */ 28 28 29 /** 30 @defgroup SharedPtr SharedPtr<T> 31 @ingroup Util Object 32 */ 33 34 /** 35 @file 36 @ingroup Util SharedPtr 37 @brief Definition of the SharedPtr template that is used to manage pointers. 38 39 @anchor SharedPtrExample 40 41 The orxonox::SharedPtr template can be used to manage a pointer to an object 42 that was created with new. The SharedPtr acts like the pointer itself, but it 43 keeps track of the number of references to it. If all references are removed, 44 SharedPtr deletes the managed object automatically. 45 46 Example: 47 48 Classic implementation using new and delete: 49 @code 50 void someFunction() 51 { 52 MyClass* object = new MyClass(); // Create a new instance of MyClass 53 54 object->myFunction(); // Calls MyClass::myFunction() 55 56 delete object; // Delete the object at the end of the scope 57 } 58 @endcode 59 60 The same function using SharedPtr: 61 @code 62 void someFunction() 63 { 64 SharedPtr<MyClass> object = new MyClass(); // Create a new instance of MyClass and store its pointer in a SharedPtr 65 66 object->myFunction(); // Calls MyClass::myFunction() 67 68 } // At the end of the scope, the SharedPtr is destroyed. Because no other SharedPtrs 69 // point at the object, the object itself is also destroyed automatically 70 @endcode 71 72 This is especially handy if you do not know what will happen with an object that was 73 created with new, for example if you pass it to another object. If multiple instances 74 share a pointer to the same object, none of these instances can delete the object 75 without interfering with the other instances. But if none of the instances destroy the 76 object, it will never be destroyed and results in a memory leak. With a SharedPtr 77 however you don't have to think about destroying the object, because the SharedPtr 78 itself keeps track of the references. 79 80 Example: 81 82 Classic implementation using new and delete: 83 @code 84 class OtherClass // Declaration of some class 85 { 86 public: 87 OtherClass(MyClass* object) // Constructor 88 { 89 this->object_ = object; // Assigns the pointer to the member variable object_ 90 } 91 92 ~OtherClass() // Destructor 93 { 94 ??? // What to do with object_? 95 } 96 97 private: 98 MyClass* object_; // A pointer to the object 99 }; 100 101 void someFunction() 102 { 103 MyClass* object = new MyClass(); // Create a new instance of MyClass 104 105 OtherClass* other1 = new OtherClass(object); // Create an instance of OtherClass and pass the object pointer 106 OtherClass* other2 = new OtherClass(object); // " 107 OtherClass* other3 = new OtherClass(object); // " 108 109 ??? // What happens with object now? 110 } 111 @endcode 112 113 If you use SharedPtr<MyClass> instead of a classic MyClass* pointer, the instance of 114 MyClass would be automatically destroyed if all instances of OtherClass are destroyed. 115 You don't need any code in the destructor and you can completely forget about the 116 object, because its managed by the SharedPtr. 117 118 The same code using SharedPtr: 119 @code 120 class OtherClass // Declaration of some class 121 { 122 public: 123 OtherClass(const SharedPtr<MyClass>& object) // Constructor 124 { 125 this->object_ = object; // Assigns the pointer to the member variable object_ 126 } 127 128 private: 129 SharedPtr<MyClass> object_; // A SharedPtr to the object 130 }; 131 132 void someFunction() 133 { 134 SharedPtr<MyClass> object = new MyClass(); // Create a new instance of MyClass 135 136 OtherClass* other1 = new OtherClass(object); // Create an instance of OtherClass and pass the object pointer 137 OtherClass* other2 = new OtherClass(object); // " 138 OtherClass* other3 = new OtherClass(object); // " 139 140 } // The SmartPtr "object" is destroyed at the end of the scope, 141 // but the three instances of OtherClass keep the object alive 142 // until they are all destroyed. 143 @endcode 144 */ 145 29 146 #ifndef _SharedPtr_H__ 30 147 #define _SharedPtr_H__ … … 39 156 namespace orxonox 40 157 { 41 class SharedCounter 42 { 43 public: 44 SharedCounter() : count_(1) {} 45 virtual void destroy() = 0; 46 47 int count_; 48 }; 49 50 template <class T> 51 class SharedCounterImpl : public SharedCounter 52 { 53 public: 54 SharedCounterImpl(T* pointer) : pointer_(pointer) {} 55 56 void destroy() 57 { 58 delete this->pointer_; 59 } 60 61 private: 62 T* pointer_; 63 }; 64 65 _UtilExport SmallObjectAllocator& createSharedCounterPool(); 66 67 FORCEINLINE SmallObjectAllocator& getSharedCounterPool() 68 { 69 static SmallObjectAllocator& instance = createSharedCounterPool(); 70 return instance; 158 namespace detail 159 { 160 /// BaseClass of SharedCounterImpl, has a counter that is initialized with 1 161 class SharedCounter 162 { 163 public: 164 SharedCounter() : count_(1) {} 165 virtual void destroy() = 0; 166 167 int count_; 168 }; 169 170 /// Child class of SharedCounter, keeps a pointer to an object of type T that can be destroyed with destroy() 171 template <class T> 172 class SharedCounterImpl : public SharedCounter 173 { 174 public: 175 SharedCounterImpl(T* pointer) : pointer_(pointer) {} 176 177 void destroy() 178 { 179 delete this->pointer_; 180 } 181 182 private: 183 T* pointer_; 184 }; 185 186 _UtilExport SmallObjectAllocator& createSharedCounterPool(); 187 188 FORCEINLINE SmallObjectAllocator& getSharedCounterPool() 189 { 190 static SmallObjectAllocator& instance = createSharedCounterPool(); 191 return instance; 192 } 71 193 } 72 194 195 /** 196 @brief The SharedPtr template is a utility to manage pointers to an object. 197 @param T The type of the managed object 198 199 SharedPtr acts like a real pointer, except that it keeps track of the number of 200 references to the object. If the the number of references drops to zero, the 201 object is destroyed automatically. 202 203 @see See @ref SharedPtrExample "this description" for some examples and more information. 204 205 @note The number of references is stored in a separate object that is shared 206 among all instances of SharedPtr that point to the same pointer. This object is 207 also responsible for destroying the pointer if the reference counter becomes zero. 208 */ 73 209 template <class T> 74 210 class SharedPtr … … 78 214 79 215 public: 216 /// Default constructor, the pointer is set to NULL. 80 217 inline SharedPtr() : pointer_(0), counter_(0) 81 218 { 82 219 } 83 220 221 /// Constructor, creates a SharedPtr that points to @a pointer, increments the counter. 84 222 inline SharedPtr(T* pointer) : pointer_(pointer), counter_(0) 85 223 { 86 224 if (this->pointer_) 87 225 { 88 void* chunk = getSharedCounterPool().alloc();89 this->counter_ = new (chunk) SharedCounterImpl<T>(this->pointer_);226 void* chunk = detail::getSharedCounterPool().alloc(); 227 this->counter_ = new (chunk) detail::SharedCounterImpl<T>(this->pointer_); 90 228 } 91 229 } 92 230 231 /// Copy-constructor, this SharedPtr now points to the same object like the other SharedPtr, increments the counter. 93 232 inline SharedPtr(const SharedPtr& other) : pointer_(other.pointer_), counter_(other.counter_) 94 233 { … … 97 236 } 98 237 238 /// Copy-constructor for SharedPtr with another template agument, increments the counter. 99 239 template <class O> 100 240 inline SharedPtr(const SharedPtr<O>& other) : pointer_(other.pointer_), counter_(other.counter_) … … 104 244 } 105 245 246 /// Destructor, decrements the counter and deletes the object if the counter becomes zero. 106 247 inline ~SharedPtr() 107 248 { … … 113 254 { 114 255 this->counter_->destroy(); 115 getSharedCounterPool().free(this->counter_);256 detail::getSharedCounterPool().free(this->counter_); 116 257 } 117 258 } 118 259 } 119 260 261 /// Assigns a new object, decrements the counter of the old object, increments the counter of the new object. 120 262 inline SharedPtr& operator=(const SharedPtr& other) 121 263 { … … 124 266 } 125 267 268 /// Assigns a new object with another template argument, decrements the counter of the old object, increments the counter of the new object. 126 269 template <class O> 127 270 inline SharedPtr& operator=(const SharedPtr<O>& other) … … 131 274 } 132 275 276 /// Casts the pointer to another type 133 277 template <class O> 134 278 inline SharedPtr<O> cast() const … … 138 282 } 139 283 284 /// Overloaded -> operator, returns the pointer to the managed object. 140 285 inline T* operator->() const 141 286 { … … 144 289 } 145 290 291 /// Overloaded * operator, returns a reference ot the managed object. 146 292 inline T& operator*() const 147 293 { … … 150 296 } 151 297 298 /// Returns the pointer to the managed object. 152 299 inline T* get() const 153 300 { … … 155 302 } 156 303 304 /// Returns true if the pointer is not NULL. 157 305 inline operator bool() const 158 306 { … … 160 308 } 161 309 310 /// Swaps the pointer and the counter of two instances of SharedPtr with the same template argument. 162 311 inline void swap(SharedPtr& other) 163 312 { … … 167 316 168 317 private: 169 inline SharedPtr(T* pointer, SharedCounter* counter) : pointer_(pointer), counter_(counter) 318 /// Private constructor, used by the cast() function. 319 inline SharedPtr(T* pointer, detail::SharedCounter* counter) : pointer_(pointer), counter_(counter) 170 320 { 171 321 if (this->pointer_) … … 173 323 } 174 324 175 T* pointer_; 176 SharedCounter* counter_;325 T* pointer_; ///< A pointer to the managed object of type @a T 326 detail::SharedCounter* counter_; ///< A pointer to the shared reference counter 177 327 }; 178 328 329 /** 330 @brief A child class of SharedPtr, used to reflect the hierarchy of the underlying class @a T. 331 @param T The type of the managed object 332 @param Parent The type of the SharedPtr that manages the parent class of @a T 333 334 This class is used to reflect the hierarchy of the underlying class @a T. 335 For example the @c Functor classes: While a @c Functor* pointer would be managed by 336 @c SharedPtr<Functor>, the child class @c FunctorStatic is managed by the class 337 <tt>SharedChildPtr<FunctorStatic, SharedPtr<Functor> ></tt>. 338 339 The second template argument @a Parent is used as the parent class of 340 SharedChildPtr. This means that each instance of <tt>SharedChildPtr<T, Parent></tt> 341 can be upcasted to @c Parent. 342 343 So for example this works: 344 @code 345 SharedChildPtr<FunctorStatic, SharedPtr<Functor> > functorStatic = createFunctor(&MyClass::myStaticFunction); 346 SharedPtr<Functor> functor = functorStatic; 347 @endcode 348 349 @note There are some typedefs and more to make the usage of SharedChildPtr easier 350 for the classes Functor and Executor. See FunctorPtr.h and ExecutorPtr.h. The above 351 example could thus be simplified the following way: 352 @code 353 FunctorStaticPtr functorStatic = createFunctor(&MyClass::myStaticFunction); 354 FunctorPtr functor = functorStatic; 355 @endcode 356 357 @see See SharedPtr for more information about the base class SharedPtr. 358 @see See @ref SharedPtrExample "this description" for some examples about how to use SharedPtr. 359 */ 179 360 template <class T, class Parent> 180 361 class SharedChildPtr : public Parent
Note: See TracChangeset
for help on using the changeset viewer.