refcounted.cc

Go to the documentation of this file.
00001 
00003 
00004 //
00005 // Copyright (c) 2000-2004 California Institute of Technology
00006 // Copyright (c) 2004-2007 University of Southern California
00007 // Rob Peters <rjpeters at usc dot edu>
00008 //
00009 // created: Sun Oct 22 14:40:28 2000
00010 // commit: $Id: refcounted.cc 10065 2007-04-12 05:54:56Z rjpeters $
00011 // $HeadURL: file:///lab/rjpeters/svnrepo/code/trunk/groovx/src/nub/refcounted.cc $
00012 //
00013 // --------------------------------------------------------------------
00014 //
00015 // This file is part of GroovX.
00016 //   [http://ilab.usc.edu/rjpeters/groovx/]
00017 //
00018 // GroovX is free software; you can redistribute it and/or modify it
00019 // under the terms of the GNU General Public License as published by
00020 // the Free Software Foundation; either version 2 of the License, or
00021 // (at your option) any later version.
00022 //
00023 // GroovX is distributed in the hope that it will be useful, but
00024 // WITHOUT ANY WARRANTY; without even the implied warranty of
00025 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00026 // General Public License for more details.
00027 //
00028 // You should have received a copy of the GNU General Public License
00029 // along with GroovX; if not, write to the Free Software Foundation,
00030 // Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
00031 //
00033 
00034 #ifndef GROOVX_NUB_REFCOUNTED_CC_UTC20050626084018_DEFINED
00035 #define GROOVX_NUB_REFCOUNTED_CC_UTC20050626084018_DEFINED
00036 
00037 #include "refcounted.h"
00038 
00039 #include "rutz/error.h"
00040 
00041 #include <limits>
00042 
00043 #include <typeinfo>
00044 
00045 #ifndef GVX_NO_PROF
00046 #define GVX_NO_PROF
00047 #endif
00048 
00049 #include "rutz/trace.h"
00050 #include "rutz/debug.h"
00051 GVX_DBG_REGISTER
00052 
00054 //
00055 // ref_counts member definitions
00056 //
00058 
00059 void* nub::ref_counts::operator new(size_t bytes)
00060 {
00061   return ::operator new(bytes);
00062 }
00063 
00064 void nub::ref_counts::operator delete(void* space, size_t /*bytes*/)
00065 {
00066   ::operator delete(space);
00067 }
00068 
00069 nub::ref_counts::ref_counts() throw() :
00070   m_strong(),
00071   m_weak(),
00072   m_owner_alive(true),
00073   m_volatile(false)
00074 {
00075 GVX_TRACE("nub::ref_counts::ref_counts");
00076 }
00077 
00078 nub::ref_counts::~ref_counts() throw()
00079 {
00080 GVX_TRACE("nub::ref_counts::~ref_counts");
00081 
00082   if (m_strong.atomic_get() > 0) GVX_PANIC("ref_counts object destroyed before strong refcount fell to 0");
00083   if (m_weak.atomic_get() > 0) GVX_PANIC("ref_counts object destroyed before weak refcount fell to 0");
00084 }
00085 
00086 void nub::ref_counts::acquire_weak() throw()
00087 {
00088 GVX_TRACE("nub::ref_counts::acquire_weak");
00089 
00090   if (m_weak.atomic_incr_return() == rutz::atomic_int_t::max_value())
00091     GVX_PANIC("weak refcount overflow");
00092 }
00093 
00094 int nub::ref_counts::release_weak() throw()
00095 {
00096 GVX_TRACE("nub::ref_counts::release_weak");
00097 
00098   const int result = m_weak.atomic_decr_return();
00099 
00100   if (result < 0) GVX_PANIC("weak refcount already 0 in release_weak()");
00101 
00102   if (result == 0)
00103     {
00104       if (m_strong.atomic_get() > 0) GVX_PANIC("weak refcount fell to 0 before strong refcount");
00105       delete this;
00106     }
00107 
00108   return result;
00109 }
00110 
00111 void nub::ref_counts::acquire_strong() throw()
00112 {
00113 GVX_TRACE("nub::ref_counts::acquire_strong");
00114 
00115   if (m_volatile) GVX_PANIC("attempt to use strong refcount with volatile object");
00116   if (m_strong.atomic_incr_return() == rutz::atomic_int_t::max_value())
00117     GVX_PANIC("strong refcount overflow");
00118 }
00119 
00120 int nub::ref_counts::release_strong() throw()
00121 {
00122 GVX_TRACE("nub::ref_counts::release_strong");
00123 
00124   if (m_volatile) GVX_PANIC("attempt to use strong refcount with volatile object");
00125   if (m_weak.atomic_get() == 0) GVX_PANIC("weak refcount prematurely fell to 0");
00126 
00127   const int result = m_strong.atomic_decr_return();
00128 
00129   if (result < 0) GVX_PANIC("strong refcount already 0 in release_strong()");
00130 
00131   return result;
00132 }
00133 
00134 void nub::ref_counts::release_strong_no_delete() throw()
00135 {
00136 GVX_TRACE("nub::ref_counts::release_strong_no_delete");
00137 
00138   const int result = m_strong.atomic_decr_return();
00139 
00140   if (result < 0) GVX_PANIC("strong refcount already 0 in release_strong_no_delete()");
00141 }
00142 
00143 void nub::ref_counts::debug_dump() const throw()
00144 {
00145   dbg_eval_nl(0, this);
00146   dbg_eval_nl(0, m_strong.atomic_get());
00147   dbg_eval_nl(0, m_weak.atomic_get());
00148   dbg_eval_nl(0, m_owner_alive);
00149 }
00150 
00152 //
00153 // ref_counted member definitions
00154 //
00156 
00157 void* nub::ref_counted::operator new(size_t bytes)
00158 {
00159 GVX_TRACE("nub::ref_counted::operator new");
00160   return ::operator new(bytes);
00161 }
00162 
00163 void nub::ref_counted::operator delete(void* space, size_t /*bytes*/)
00164 {
00165 GVX_TRACE("nub::ref_counted::operator delete");
00166   ::operator delete(space);
00167 }
00168 
00169 nub::ref_counted::ref_counted() :
00170   m_ref_counts(new nub::ref_counts)
00171 {
00172 GVX_TRACE("nub::ref_counted::ref_counted");
00173   dbg_print(7, "ref_counted ctor"); dbg_eval_nl(7, this);
00174 
00175   m_ref_counts->acquire_weak();
00176 }
00177 
00178 nub::ref_counted::~ref_counted() GVX_DTOR_NOTHROW
00179 {
00180 GVX_TRACE("nub::ref_counted::~ref_counted");
00181   dbg_print(7, "ref_counted dtor"); dbg_eval_nl(7, this);
00182   dbg_dump(7, *m_ref_counts);
00183 
00184   // Must guarantee that (strong-count == 0) when the refcounted object is
00185   // destroyed. Without that guarantee, weak references will be messed up,
00186   // since they'll think that the object is still alive (i.e. strong
00187   // refcount > 0) when it actually is already destroyed.
00188   if (m_ref_counts->m_strong.atomic_get() > 0)
00189     GVX_PANIC("ref_counted object destroyed before strong refcount dropped to 0");
00190 
00191   m_ref_counts->m_owner_alive = false;
00192   m_ref_counts->release_weak();
00193 }
00194 
00195 void nub::ref_counted::mark_as_volatile() throw()
00196 {
00197 GVX_TRACE("nub::ref_counted::mark_as_volatile");
00198   if (m_ref_counts->m_strong.atomic_get() > 0)
00199     GVX_PANIC("can't make volatile object that already has strong refs");
00200 
00201   if (m_ref_counts->m_volatile)
00202     GVX_PANIC("object already marked as volatile");
00203 
00204   m_ref_counts->m_volatile = true;
00205 }
00206 
00207 void nub::ref_counted::incr_ref_count() const throw()
00208 {
00209   m_ref_counts->acquire_strong();
00210 }
00211 
00212 void nub::ref_counted::decr_ref_count() const throw()
00213 {
00214   if (m_ref_counts->release_strong() == 0)
00215     {
00216       dbg_eval_nl(3, typeid(*this).name());
00217       delete this;
00218     }
00219 }
00220 
00221 void nub::ref_counted::decr_ref_count_no_delete() const throw()
00222 {
00223   m_ref_counts->release_strong_no_delete();
00224 }
00225 
00226 bool nub::ref_counted::is_shared() const throw()
00227 {
00228 GVX_TRACE("nub::ref_counted::is_shared");
00229 
00230   return (m_ref_counts->m_strong.atomic_get() > 1) || is_not_shareable();
00231   // We check is_not_shareable() so that volatile objects always appear
00232   // shared, so that they cannot be removed from the nub::objectdb until
00233   // they become invalid.
00234 }
00235 
00236 bool nub::ref_counted::is_unshared() const throw()
00237 {
00238 GVX_TRACE("nub::ref_counted::is_unshared");
00239   return !is_shared();
00240 }
00241 
00242 bool nub::ref_counted::is_not_shareable() const throw()
00243 {
00244 GVX_TRACE("nub::ref_counted::is_not_shareable");
00245   return m_ref_counts->m_volatile;
00246 }
00247 
00248 nub::ref_counts* nub::ref_counted::get_counts() const throw()
00249 {
00250 GVX_TRACE("nub::ref_counted::get_counts");
00251   return m_ref_counts;
00252 }
00253 
00254 int nub::ref_counted::dbg_ref_count() const throw()
00255 {
00256   return m_ref_counts->m_strong.atomic_get();
00257 }
00258 
00259 int nub::ref_counted::dbg_weak_ref_count() const throw()
00260 {
00261   return m_ref_counts->m_weak.atomic_get();
00262 }
00263 
00264 static const char __attribute__((used)) vcid_groovx_nub_refcounted_cc_utc20050626084018[] = "$Id: refcounted.cc 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00265 #endif // !GROOVX_NUB_REFCOUNTED_CC_UTC20050626084018_DEFINED

The software described here is Copyright (c) 1998-2005, Rob Peters.
This page was generated Wed Dec 3 06:49:39 2008 by Doxygen version 1.5.5.