refcounted.h

Go to the documentation of this file.
00001 /** @file nub/refcounted.h reference-counted base class, allowing
00002     intrusive smart pointers to be used */
00003 
00004 ///////////////////////////////////////////////////////////////////////
00005 //
00006 // Copyright (c) 2000-2004 California Institute of Technology
00007 // Copyright (c) 2004-2007 University of Southern California
00008 // Rob Peters <rjpeters at usc dot edu>
00009 //
00010 // created: Sun Oct 22 14:40:19 2000
00011 // commit: $Id: refcounted.h 8249 2007-04-12 06:03:40Z rjpeters $
00012 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/nub/refcounted.h $
00013 //
00014 // --------------------------------------------------------------------
00015 //
00016 // This file is part of GroovX.
00017 //   [http://ilab.usc.edu/rjpeters/groovx/]
00018 //
00019 // GroovX is free software; you can redistribute it and/or modify it
00020 // under the terms of the GNU General Public License as published by
00021 // the Free Software Foundation; either version 2 of the License, or
00022 // (at your option) any later version.
00023 //
00024 // GroovX is distributed in the hope that it will be useful, but
00025 // WITHOUT ANY WARRANTY; without even the implied warranty of
00026 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00027 // General Public License for more details.
00028 //
00029 // You should have received a copy of the GNU General Public License
00030 // along with GroovX; if not, write to the Free Software Foundation,
00031 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00032 //
00033 ///////////////////////////////////////////////////////////////////////
00034 
00035 #ifndef GROOVX_NUB_REFCOUNTED_H_UTC20050626084018_DEFINED
00036 #define GROOVX_NUB_REFCOUNTED_H_UTC20050626084018_DEFINED
00037 
00038 #include "rutz/atomic.h"
00039 
00040 #include <cstdlib>
00041 
00042 namespace nub
00043 {
00044   class ref_counts;
00045   class ref_counted;
00046 }
00047 
00048 
00049 // If we want to enforce that destructors of objects derived form
00050 // nub::ref_counted (and nub::object) should have an empty throw-spec
00051 // (i.e. "throw()"), then need "#define GVX_DTOR_NOTHROW throw()",
00052 // otherwise we just define GVX_DTOR_NOTHROW to be empty
00053 #ifndef GVX_DTOR_NOTHROW
00054 #  define GVX_DTOR_NOTHROW
00055 #endif
00056 
00057 ///////////////////////////////////////////////////////////////////////
00058 /**
00059  *
00060  * nub::ref_counts manages strong+weak reference counts for
00061  * nub::ref_counted objects. Its main purpose is to allow weak
00062  * ref-counting; a client who wants to do weak ref-counting can get a
00063  * hold of the nub::ref_counted object's nub::ref_counts, and then check
00064  * whether is_owner_alive() to know whether the nub::ref_counted object
00065  * is still valid. This technique is implemented by nub::soft_ref. The
00066  * nub::ref_counts object will delete itself when both its strong and
00067  * weak counts go to 0.
00068  *
00069  **/
00070 ///////////////////////////////////////////////////////////////////////
00071 
00072 struct nub::ref_counts
00073 {
00074 public:
00075   friend class nub::ref_counted;
00076 
00077   void* operator new(size_t bytes);
00078   void operator delete(void* space, size_t bytes);
00079 
00080   ref_counts() throw();
00081 
00082 private:
00083   /// Private destructor since the object destroys itself eventually in release_weak().
00084   ~ref_counts() throw();
00085 
00086 public:
00087 
00088   bool is_owner_alive() const throw() { return m_owner_alive; }
00089 
00090   void acquire_weak() throw();
00091   int release_weak() throw();
00092 
00093   void debug_dump() const throw();
00094 
00095 private:
00096   ref_counts(const ref_counts&) throw();
00097   ref_counts& operator=(const ref_counts&) throw();
00098 
00099   void acquire_strong() throw();
00100   int release_strong() throw();
00101   void release_strong_no_delete() throw();
00102 
00103   rutz::atomic_int_t m_strong;
00104   rutz::atomic_int_t m_weak;
00105   bool m_owner_alive;
00106   bool m_volatile;
00107 };
00108 
00109 
00110 
00111 ///////////////////////////////////////////////////////////////////////
00112 /**
00113  *
00114  * nub::ref_counted is a reference counting base class that allows both
00115  * strong and weak reference counting. nub::ref_counted objects use a
00116  * nub::ref_counts object to manage their reference counts, so clients
00117  * that need to know if a nub::ref_counted object is still around can
00118  * check the is_owner_alive() from its nub::ref_counts object. Finally,
00119  * subclasses of nub::ref_counted can declare themselves volatile (by
00120  * calling mark_as_volatile()) if their lifetime cannot be fully
00121  * controlled by reference-counting; clients of such volatile objects
00122  * must use weak reference counts only. No manipulation of the
00123  * reference count is allowed for volatile objects; only the weak
00124  * reference count may be used.
00125  *
00126  **/
00127 ///////////////////////////////////////////////////////////////////////
00128 
00129 class nub::ref_counted
00130 {
00131 private:
00132   ref_counts* const m_ref_counts;
00133 
00134   // These are disallowed since ref_counted's should always be in
00135   // one-to-one correspondence with their pointee's.
00136   ref_counted(const ref_counted& other);
00137   ref_counted& operator=(const ref_counted& other);
00138 
00139   // If GVX_ENFORCE_FACTORY_FUNCTIONS, then we make operator new() and
00140   // delete() protected, as well as the default constructor and
00141   // destructor. This means that only derived classes can use operator
00142   // new() and delete(), and that thus derived classes are required to
00143   // define functions of the form "static nub::ref<derived_class>
00144   // make() { return nub::ref<derived_class>(new derived_class)."
00145   // While this is a bit of extra typing, it helps ensure that
00146   // ref_counted objects are not constructed on the stack, and are not
00147   // handled by the wrong type of smart pointer (such as a
00148   // shared_ptr).
00149 #ifdef GVX_ENFORCE_FACTORY_FUNCTIONS
00150 protected:
00151 #else
00152 public:
00153 #endif
00154 
00155   /** Class-specific operator new; protected to ensure that clients
00156       use factory functions. */
00157   void* operator new(size_t bytes);
00158 
00159   /** Class-specific operator delete; private since deletion should
00160       only happen in ref_counted::decr_ref_count. */
00161   void operator delete(void* space, size_t bytes);
00162 
00163   /// Default constructor.
00164   ref_counted();
00165 
00166   /** Virtual destructor is protected, so that we can prevent clients
00167       from instantiating ref_counted's on the stack and from destroying
00168       them explicitly. Instead, ref_counted objects will only be
00169       destroyed by a 'delete this' call inside decr_ref_count() if the
00170       reference count falls to zero or below. Clients are forced to
00171       create ref_counted objects dynamically using \c new, which is
00172       what we need in order for 'delete this' to be valid later on. */
00173   virtual ~ref_counted() GVX_DTOR_NOTHROW;
00174 
00175   /// Mark this object as a volatile (unshareable) object.
00176   void mark_as_volatile() throw();
00177 
00178 public:
00179   /// Increment the object's reference count.
00180   /** This operation (on the strong reference count) is not permitted if
00181       the object is unshareable. Unshareable objects can only have their
00182       weak reference counts manipulated. */
00183   void incr_ref_count() const throw();
00184 
00185   /// Decrement the object's reference count.
00186   /** If this causes the reference count to fall to zero or below, the
00187       pointee and the pointer will be destroyed by a call to 'delete
00188       this'. This operation (on the strong reference count) is not
00189       permitted if the object is unshareable. Unshareable objects can only
00190       have their weak reference counts manipulated. */
00191   void decr_ref_count() const throw();
00192 
00193   /// Decrement the object's reference count, but don't delete it.
00194   /** Unlike decr_ref_count(), the object will NOT be delete'd if the
00195       reference count falls to zero. This operation (on the strong
00196       reference count) is not permitted if the object is
00197       unshareable. Unshareable objects can only have their weak reference
00198       counts manipulated. */
00199   void decr_ref_count_no_delete() const throw();
00200 
00201   /// Returns true if no external client has sole ownership of the object.
00202   /** This may occur if either (1) the reference count is greater than one,
00203       or (2) the object is_not_shareable(), meaning that the object itself is
00204       the only "owner". */
00205   bool is_shared() const throw();
00206 
00207   /// Returns true if there is a sole external owner of the object.
00208   /** This occurs if the reference count is one or less and the object is
00209       shareable. */
00210   bool is_unshared() const throw();
00211 
00212   /** Returns true if the object is not shareable for any reason. This
00213       could be because its lifespan is volatile (such as objects
00214       representing on-screen windows that can be dismissed by the
00215       user). The default is for objects to be shareable; objects can
00216       declare themselves as unshareable by calling mark_as_volatile(). */
00217   bool is_not_shareable() const throw();
00218 
00219   /// Returns the object's reference count manager.
00220   ref_counts* get_counts() const throw();
00221 
00222 
00223   /// FOR TEST/DEBUG ONLY! Returns the object's (strong) reference count.
00224   int dbg_ref_count() const throw();
00225 
00226   /// FOR TEST/DEBUG ONLY! Returns the object's weak reference count.
00227   int dbg_weak_ref_count() const throw();
00228 };
00229 
00230 static const char __attribute__((used)) vcid_groovx_nub_refcounted_h_utc20050626084018[] = "$Id: refcounted.h 8249 2007-04-12 06:03:40Z rjpeters $ $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/nub/refcounted.h $";
00231 #endif // !GROOVX_NUB_REFCOUNTED_H_UTC20050626084018_DEFINED
Generated on Sun May 8 08:41:08 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3