00001 # if !defined(TS_INTRUSIVE_PTR_HEADER) 00002 # define TS_INTRUSIVE_PTR_HEADER 00003 00004 /** @file 00005 00006 This is a simple shared pointer class for restricted use. It is not a 00007 completely general class. The most significant missing feature is the 00008 lack of thread safety. For its intended use, this is acceptable and 00009 provides a performance improvement. However, it does restrict how the 00010 class may be used. 00011 00012 This style of shared pointer also requires explicit support from the 00013 target class, which must provide an internal reference counter. 00014 00015 @section license License 00016 00017 Licensed to the Apache Software Foundation (ASF) under one 00018 or more contributor license agreements. See the NOTICE file 00019 distributed with this work for additional information 00020 regarding copyright ownership. The ASF licenses this file 00021 to you under the Apache License, Version 2.0 (the 00022 "License"); you may not use this file except in compliance 00023 with the License. You may obtain a copy of the License at 00024 00025 http://www.apache.org/licenses/LICENSE-2.0 00026 00027 Unless required by applicable law or agreed to in writing, software 00028 distributed under the License is distributed on an "AS IS" BASIS, 00029 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00030 See the License for the specific language governing permissions and 00031 limitations under the License. 00032 */ 00033 00034 # include <sys/types.h> 00035 # include <assert.h> 00036 # include <functional> 00037 00038 namespace ts { 00039 00040 class IntrusivePtrCounter; 00041 00042 /** This class exists solely to be declared a friend of @c IntrusivePtrCounter. 00043 00044 @internal This is done because we can't declare the template a 00045 friend, so rather than burden the client with the declaration we 00046 do it here. It provides a single method that allows the smart pointer 00047 to get access to the protected reference count. 00048 00049 */ 00050 class IntrusivePtrBase { 00051 public: 00052 /// Type used for reference counter. 00053 typedef long Counter; 00054 protected: 00055 Counter* getCounter( 00056 IntrusivePtrCounter* c ///< Cast object with reference counter. 00057 ) const; 00058 }; 00059 /* ----------------------------------------------------------------------- */ 00060 /* ----------------------------------------------------------------------- */ 00061 /** Reference counter mixin. 00062 00063 To add support for @c IntrusivePtr to class @a T, it 00064 should inherit from @c IntrusivePtrCounter<T> in order to 00065 00066 - provide a reference count member 00067 - force the reference count to initialize to zero 00068 - define the add and release global functions required by @c IntrusivePtr 00069 00070 In general this class should be inherited publicly. This will 00071 provide methods which mimic the @c Boost.shared_ptr interface ( @c 00072 unique() , @c use_count() ). 00073 00074 If this class is not inherited publically or the destructor is 00075 non-public then the host class (@a T) must declare this class ( @c 00076 reference_counter<T> ) as a friend. 00077 00078 @internal Due to changes in the C++ standard and design decisions 00079 in gcc, it is no longer possible to declare a template parameter 00080 as a friend class. (Basically, you can't use a typedef in a 00081 friend declaration and gcc treats template parameters as 00082 typedefs). 00083 00084 @note You can use this with insulated (by name only) classes. The 00085 important thing is to make sure that any such class that uses @c 00086 IntrusivePtr has all of its constructors and destructors declared 00087 in the header and defined in the implementation translation 00088 unit. If the compiler generates any of those, it will not compile 00089 due to missing functions or methods 00090 00091 */ 00092 class IntrusivePtrCounter { 00093 friend class IntrusivePtrBase; 00094 public: 00095 /** Copy constructor. 00096 00097 @internal We have to define this to explicitly _not_ copy the 00098 reference count. Otherwise any client that uses a default copy 00099 constructor will _copy the ref count into the new object_. That 00100 way lies madness. 00101 */ 00102 00103 IntrusivePtrCounter( 00104 IntrusivePtrCounter const& ///< Source object. 00105 ); 00106 00107 /** Assignment operator. 00108 00109 @internal We need this for the same reason as the copy 00110 constructor. The reference counter must not participate in 00111 assignment. 00112 */ 00113 IntrusivePtrCounter& operator = ( 00114 IntrusivePtrCounter const& 00115 ); 00116 00117 protected: 00118 IntrusivePtrBase::Counter m_intrusive_pointer_reference_count; 00119 /// Default constructor (0 init counter). 00120 /// @internal Only subclasses can access this. 00121 IntrusivePtrCounter(); 00122 }; 00123 /* ----------------------------------------------------------------------- */ 00124 /* ----------------------------------------------------------------------- */ 00125 /** Shared pointer. 00126 00127 This is a reference counted smart pointer. A single object is jointly 00128 ownded by a set of pointers. When the last of the pointers is destructed 00129 the target object is also destructed. 00130 00131 The smart pointer actions can be changed through class specific policy 00132 by specializing the @c IntrusivePtrPolicy template class. 00133 */ 00134 template < typename T > 00135 class IntrusivePtr : private IntrusivePtrBase { 00136 private: /* don't pollute client with these typedefs */ 00137 typedef IntrusivePtrBase super; ///< Parent type. 00138 typedef IntrusivePtr self; ///< Self reference type. 00139 00140 public: 00141 /// Promote type for reference counter. 00142 typedef super::Counter Counter; 00143 00144 /// Default constructor (0 initialized). 00145 IntrusivePtr(); 00146 /// Construct from instance. 00147 /// The instance becomes referenced and owned by the pointer. 00148 IntrusivePtr(T* obj); 00149 /// Destructor. 00150 ~IntrusivePtr(); 00151 00152 /// Copy constructor. 00153 IntrusivePtr(const self& src); 00154 /// Self assignement. 00155 self& operator = (const self& src); 00156 /** Assign from instance. 00157 The instance becomes referenced and owned by the pointer. 00158 The reference to the current object is dropped. 00159 */ 00160 self& operator = ( 00161 T* obj ///< Target instance. 00162 ); 00163 00164 /** Assign from instance. 00165 The instance becomes referenced and owned by the pointer. 00166 The reference to the current object is dropped. 00167 @note A synonym for @c operator= for compatibility. 00168 */ 00169 self& assign ( 00170 T* obj ///< Target instance. 00171 ); 00172 00173 /** Assign from instance. 00174 The instance becomes referenced and owned by the pointer. 00175 The reference to the current object is dropped. 00176 */ 00177 void reset(T* obj); 00178 /** Clear reference without cleanup. 00179 00180 This unsets this smart pointer and decrements the reference 00181 count, but does @b not perform any finalization on the 00182 target object. This can easily lead to memory leaks and 00183 in some sense vitiates the point of this class, but it is 00184 occasionally the right thing to do. Use with caution. 00185 00186 @return @c true if there are no references upon return, 00187 @c false if the reference count is not zero. 00188 */ 00189 bool release(); 00190 00191 /// Test if the pointer is zero (@c NULL). 00192 bool isNull() const; 00193 00194 /// Member dereference. 00195 T* operator -> () const; 00196 /// Dereference. 00197 T& operator * () const; 00198 /// Access raw pointer. 00199 T* get() const; 00200 00201 /** User conversion to raw pointer. 00202 00203 @internal allow implicit conversion to the underlying 00204 pointer. This allows for the form "if (handle)" and is not 00205 particularly dangerous (as it would be for a scope_ptr or 00206 shared_ptr) because the counter is carried with the object and 00207 so can't get lost or duplicated. 00208 00209 */ 00210 operator T* () const; 00211 00212 /** Cross type construction. 00213 This succeeds if an @a X* can be implicitly converted to a @a T*. 00214 */ 00215 template < 00216 typename X ///< Foreign pointer type. 00217 > IntrusivePtr( 00218 IntrusivePtr<X> const& that ///< Foreign pointer. 00219 ); 00220 00221 /** Cross type assignment. 00222 This succeeds if an @a X* can be implicitily converted to a @a T*. 00223 */ 00224 template < 00225 typename X ///< Foreign pointer type. 00226 > self& operator = ( 00227 IntrusivePtr<X> const& that ///< Foreign pointer. 00228 ); 00229 00230 /// Check for multiple references. 00231 /// @return @c true if more than one smart pointer references the object, 00232 /// @c false otherwise. 00233 bool isShared() const; 00234 /// Check for a single reference (@c shared_ptr compatibility) 00235 /// @return @c true if this object is not shared. 00236 bool unique() const; 00237 /// Reference count. 00238 /// @return Number of references. 00239 Counter useCount() const; 00240 private: 00241 T* m_obj; ///< Pointer to object. 00242 00243 /// Reference @a obj. 00244 void set( 00245 T* obj ///< Target object. 00246 ); 00247 /// Drop the current reference. 00248 void unset(); 00249 00250 /// Get a pointer to the reference counter of the target object. 00251 Counter* getCounter() const; 00252 }; 00253 00254 /** Pointer dynamic cast. 00255 This allows a smart pointer to be cast from one type to another. 00256 It must be used when the types do not implicitly convert (generally 00257 a downcast). 00258 00259 @code 00260 class A { ... }; 00261 class B : public A { ... }; 00262 IntrusivePtr<A> really_b(new B); 00263 InstruivePtr<B> the_b; 00264 the_b = dynamic_ptr_cast<B>(really_b); 00265 @endcode 00266 */ 00267 template < 00268 typename T, ///< Target type. 00269 typename X ///< Source type. 00270 > IntrusivePtr<T> dynamic_ptr_cast( 00271 IntrusivePtr<X> const& src ///< Source pointer. 00272 ) { 00273 return IntrusivePtr<T>(dynamic_cast<T*>(src.get())); 00274 } 00275 00276 /** Pointer cast. 00277 This allows a smart pointer to be cast from one type to another. 00278 It must be used when the types do not implicitly convert (generally 00279 a downcast). This uses @c static_cast and so performs only compile 00280 time checks. 00281 00282 @code 00283 class A { ... }; 00284 class B : public A { ... }; 00285 IntrusivePtr<A> really_b(new B); 00286 IntrusivePtr<B> the_b; 00287 the_b = ptr_cast<B>(really_b); 00288 @endcode 00289 */ 00290 template < 00291 typename T, ///< Target type. 00292 typename X ///< Source type. 00293 > IntrusivePtr<T> ptr_cast( 00294 IntrusivePtr<X> const& src ///< Source pointer. 00295 ) { 00296 return IntrusivePtr<T>(static_cast<T*>(src.get())); 00297 } 00298 /* ----------------------------------------------------------------------- */ 00299 /* ----------------------------------------------------------------------- */ 00300 /** Default policy class for intrusive pointers. 00301 00302 This allows per type policy, although not per target instance. 00303 Clients can override policy by specializing this class for the 00304 target type. 00305 00306 @code 00307 template <> IntrusivePtrPolicy<SomeType> 00308 : IntrusivePtrDefaultPolicy { 00309 ... Redefinition of methods and nested types ... 00310 }; 00311 @endcode 00312 00313 The inherited class will provide the default definitions so you can 00314 override only what is different. Although this can be omitted if you 00315 override everything, it is more robust for maintenance to inherit 00316 anyway. 00317 */ 00318 00319 template <typename T> 00320 class IntrusivePtrPolicy { 00321 public: 00322 /// Called when the pointer is dereferenced. 00323 /// Default is empty (no action). 00324 static void dereferenceCheck( 00325 T* ///< Target object. 00326 ); 00327 00328 /** Perform clean up on a target object that is no longer referenced. 00329 00330 Default is calling @c delete. Any specialization that overrides this 00331 @b must clean up the object. The primary use of this is to perform 00332 a clean up other than @c delete. 00333 00334 @note When this is called, the target object reference count 00335 is zero. If it is necessary to pass a smart pointer to the 00336 target object, it will be necessary to call 00337 @c IntrusivePtr::release to drop the reference without 00338 another finalization. Further care must be taken that none of 00339 the called logic keeps a copy of the smart pointer. Use with 00340 caution. 00341 */ 00342 static void finalize( 00343 T* t ///< Target object. 00344 ); 00345 /// Strict weak order for STL containers. 00346 class Order 00347 : public std::binary_function< IntrusivePtr<T>, IntrusivePtr<T>, bool> { 00348 public: 00349 /// Default constructor. 00350 Order() { 00351 } 00352 /// Compare by raw pointer. 00353 bool operator() ( 00354 IntrusivePtr<T> const& lhs, ///< Left hand operand. 00355 IntrusivePtr<T> const& rhs ///< Right hand operand. 00356 ) const; 00357 }; 00358 }; 00359 00360 struct IntrusivePtrDefaultPolicyTag {}; 00361 typedef IntrusivePtrPolicy<IntrusivePtrDefaultPolicyTag> IntrusivePtrDefaultPolicy; 00362 /* ----------------------------------------------------------------------- */ 00363 /* ----------------------------------------------------------------------- */ 00364 /* Inline Methods */ 00365 inline IntrusivePtrCounter::IntrusivePtrCounter() 00366 : m_intrusive_pointer_reference_count(0) { 00367 } 00368 00369 inline IntrusivePtrCounter::IntrusivePtrCounter(IntrusivePtrCounter const&) 00370 : m_intrusive_pointer_reference_count(0) { 00371 } 00372 00373 inline IntrusivePtrCounter& 00374 IntrusivePtrCounter::operator = (IntrusivePtrCounter const&) { 00375 return *this; 00376 } 00377 00378 inline IntrusivePtrBase::Counter* 00379 IntrusivePtrBase::getCounter(IntrusivePtrCounter* c) const { 00380 return &(c->m_intrusive_pointer_reference_count); 00381 } 00382 /* ----------------------------------------------------------------------- */ 00383 /* ----------------------------------------------------------------------- */ 00384 template < typename T > void 00385 IntrusivePtrPolicy<T>::dereferenceCheck(T*) { 00386 } 00387 00388 template < typename T > void 00389 IntrusivePtrPolicy<T>::finalize(T* obj) { 00390 delete obj; 00391 } 00392 00393 template < typename T > bool 00394 IntrusivePtrPolicy<T>::Order::operator()( 00395 IntrusivePtr<T> const& lhs, 00396 IntrusivePtr<T> const& rhs 00397 ) const { 00398 return lhs.get() < rhs.get(); 00399 } 00400 /* ----------------------------------------------------------------------- */ 00401 /* ----------------------------------------------------------------------- */ 00402 template < typename T > 00403 IntrusivePtr<T>::IntrusivePtr() 00404 : m_obj(0) { 00405 } 00406 00407 template < typename T > 00408 IntrusivePtr<T>::IntrusivePtr(T* obj) { 00409 this->set(obj); 00410 } 00411 00412 template < typename T > 00413 IntrusivePtr<T>::~IntrusivePtr() { 00414 this->unset(); 00415 } 00416 00417 template < typename T > 00418 IntrusivePtr<T>::IntrusivePtr(const self& that) { 00419 this->set(that.m_obj); 00420 } 00421 00422 template < typename T > 00423 template < typename X > 00424 IntrusivePtr<T>::IntrusivePtr( 00425 IntrusivePtr<X> const& that ///< Foreign pointer. 00426 ) : super(that.get()) { 00427 } 00428 00429 template < typename T > IntrusivePtr<T>& 00430 IntrusivePtr<T>::operator = (const self& that) { 00431 this->reset(that.m_obj); 00432 return *this; 00433 } 00434 00435 template < typename T > 00436 template < typename X > 00437 IntrusivePtr<T>& 00438 IntrusivePtr<T>::operator = ( 00439 IntrusivePtr<X> const& that ///< Foreign pointer. 00440 ) { 00441 this->reset(that.get()); 00442 return *this; 00443 } 00444 00445 template < typename T > IntrusivePtr<T>& 00446 IntrusivePtr<T>::operator = (T* obj) { 00447 this->reset(obj); 00448 return *this; 00449 } 00450 00451 template < typename T > IntrusivePtr<T>& 00452 IntrusivePtr<T>::assign (T* obj) { 00453 return *this = obj; 00454 } 00455 00456 template < typename T > T* 00457 IntrusivePtr<T>::operator -> () const { 00458 IntrusivePtrPolicy<T>::dereferenceCheck(m_obj); 00459 return m_obj; 00460 } 00461 00462 template < typename T > T& 00463 IntrusivePtr<T>::operator * () const { 00464 IntrusivePtrPolicy<T>::dereferenceCheck(m_obj); 00465 return *m_obj; 00466 } 00467 00468 template < typename T > T* 00469 IntrusivePtr<T>::get() const { 00470 IntrusivePtrPolicy<T>::dereferenceCheck(m_obj); 00471 return m_obj; 00472 } 00473 00474 template < typename T > typename IntrusivePtr<T>::Counter* 00475 IntrusivePtr<T>::getCounter() const { 00476 return super::getCounter(static_cast<IntrusivePtrCounter*>(m_obj)); 00477 } 00478 00479 /* The Set/Unset methods are the basic implementation of our 00480 * reference counting. The Reset method is the standard way 00481 * of invoking the pair, although splitting them allows some 00482 * additional efficiency in certain situations. 00483 */ 00484 00485 /* set and unset are two half operations that don't do checks. 00486 It is the callers responsibility to do that. 00487 */ 00488 00489 template < typename T > void 00490 IntrusivePtr<T>::unset() { 00491 if (0 != m_obj) { 00492 /* magic: our target is required to inherit from IntrusivePtrCounter, 00493 * which provides a protected counter variable and access via our 00494 * super class. We call the super class method to get a raw pointer 00495 * to the counter variable. 00496 */ 00497 Counter* cp = this->getCounter(); 00498 00499 /* If you hit this assert you've got a cycle of objects that 00500 reference each other. A delete in the cycle will eventually 00501 result in one of the objects getting deleted twice, which is 00502 what this assert indicates. 00503 */ 00504 assert(*cp); 00505 00506 if (0 == --*cp) { 00507 IntrusivePtrPolicy<T>::finalize(m_obj); 00508 } 00509 m_obj = 0; 00510 } 00511 } 00512 00513 template < typename T > void 00514 IntrusivePtr<T>::set(T* obj) { 00515 m_obj = obj; /* update to new object */ 00516 if (0 != m_obj) /* if a real object, bump the ref count */ 00517 ++(*(this->getCounter())); 00518 } 00519 00520 template < typename T > void 00521 IntrusivePtr<T>::reset(T* obj) { 00522 if (obj != m_obj) { 00523 this->unset(); 00524 this->set(obj); 00525 } 00526 } 00527 00528 template < typename T > bool 00529 IntrusivePtr<T>::release() { 00530 bool zret = true; 00531 if (m_obj) { 00532 Counter* cp = this->getCounter(); 00533 zret = *cp <= 1; 00534 // If the client is using this method, they're doing something funky 00535 // so be extra careful with the reference count. 00536 if (*cp > 0) --*cp; 00537 m_obj = 0; 00538 } 00539 return zret; 00540 } 00541 00542 /* Simple method to check for invalid pointer */ 00543 template < typename T > bool 00544 IntrusivePtr<T>::isNull() const { 00545 return 0 == m_obj; 00546 } 00547 00548 /* Pointer comparison */ 00549 template < typename T > bool 00550 operator == (IntrusivePtr<T> const& lhs, IntrusivePtr<T> const& rhs) { 00551 return lhs.get() == rhs.get(); 00552 } 00553 00554 template < typename T > bool 00555 operator != (IntrusivePtr<T> const& lhs, IntrusivePtr<T> const& rhs) { 00556 return lhs.get() != rhs.get(); 00557 } 00558 00559 template < typename T > bool 00560 operator < (IntrusivePtr<T> const& lhs, IntrusivePtr<T> const& rhs) { 00561 return lhs.get() < rhs.get(); 00562 } 00563 00564 template < typename T > bool 00565 operator == (IntrusivePtr<T> const& lhs, int rhs) { 00566 assert(0 == rhs); 00567 return lhs.get() == 0; 00568 } 00569 00570 template < typename T > bool 00571 operator == (int lhs, IntrusivePtr<T> const& rhs) { 00572 assert(0 == lhs); 00573 return rhs.get() == 0; 00574 } 00575 00576 template < typename T > bool 00577 operator != (int lhs, IntrusivePtr<T> const& rhs) { 00578 return !(lhs == rhs); 00579 } 00580 00581 template < typename T > bool 00582 operator != (IntrusivePtr<T> const& lhs, int rhs) { 00583 return !(lhs == rhs); 00584 } 00585 00586 template < typename T > 00587 IntrusivePtr<T>::operator T* () const { 00588 return m_obj; 00589 } 00590 00591 template < typename T> bool 00592 IntrusivePtr<T>::isShared() const { 00593 return m_obj && *(this->getCounter()) > 1; 00594 } 00595 00596 template < typename T> bool 00597 IntrusivePtr<T>::unique() const { 00598 return 0 == m_obj || *(this->getCounter()) <= 1; 00599 } 00600 00601 template < typename T> typename IntrusivePtr<T>::Counter 00602 IntrusivePtr<T>::useCount() const { 00603 return m_obj ? *(this->getCounter()) : 0; 00604 } 00605 /* ----------------------------------------------------------------------- */ 00606 /* ----------------------------------------------------------------------- */ 00607 } // namespace ats 00608 /* ----------------------------------------------------------------------- */ 00609 # endif // TS_INTRUSIVE_PTR_HEADER