• Main Page
  • Related Pages
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

IntrusivePtr.h

Go to the documentation of this file.
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

Generated by  doxygen 1.7.1