weak_handle.h

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: Wed Nov 16 08:50:18 2005
00010 // commit: $Id: weak_handle.h 10065 2007-04-12 05:54:56Z rjpeters $
00011 // $HeadURL: file:///lab/rjpeters/svnrepo/code/trunk/groovx/src/nub/weak_handle.h $
00012 //
00013 // --------------------------------------------------------------------
00014 //
00015 // This file is part of GroovX.
00016 //   [http://www.klab.caltech.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_WEAK_HANDLE_H_UTC20051116165018_DEFINED
00035 #define GROOVX_NUB_WEAK_HANDLE_H_UTC20051116165018_DEFINED
00036 
00037 #include "nub/refcounted.h"
00038 #include "nub/types.h"
00039 
00040 #include "rutz/algo.h"         // for rutz::swap2()
00041 #include "rutz/fileposition.h" // for SRC_POS macro
00042 
00043 #include <typeinfo>
00044 
00045 namespace nub
00046 {
00047   namespace detail
00048   {
00049     template <class T> class weak_handle;
00050 
00051     void throw_soft_ref_invalid(const std::type_info& info, const rutz::file_pos& pos);
00052   }
00053 }
00054 
00056 
00059 template <class T>
00060 class nub::detail::weak_handle
00061 {
00062 private:
00063   static nub::ref_counts* get_counts(T* master, ref_type tp) throw()
00064   {
00065     return (master && (tp == WEAK || master->is_not_shareable())) ?
00066       master->get_counts() : 0;
00067   }
00068 
00069 public:
00070   weak_handle(T* master, ref_type tp) throw()
00071     :
00072     m_master(master),
00073     m_counts(get_counts(master, tp))
00074   { this->acquire(); }
00075 
00076   ~weak_handle() throw()
00077   { this->release(); }
00078 
00079   weak_handle(const weak_handle& other) throw()
00080     :
00081     m_master(other.m_master),
00082     m_counts(other.m_counts)
00083   { this->acquire(); }
00084 
00085   weak_handle& operator=(const weak_handle& other) throw()
00086   {
00087     weak_handle other_copy(other);
00088     this->swap(other_copy);
00089     return *this;
00090   }
00091 
00092   bool is_valid() const throw()
00093   {
00094     if (m_counts == 0) // implies we are using strong ref's
00095       {
00096         return (m_master != 0);
00097       }
00098 
00099     // else... (m_counts != 0) implies we are using weak ref's
00100 
00101     return m_counts->is_owner_alive();
00102   }
00103 
00104   T* get()      const         { this->ensure_valid(); return m_master; }
00105   T* get_weak() const throw() { return this->is_valid() ? m_master : 0; }
00106 
00107   ref_type get_ref_type() const throw()
00108   {
00109     return (m_master && !m_counts) ? STRONG : WEAK;
00110   }
00111 
00112 private:
00113   void acquire() const throw()
00114   {
00115     if (m_master)
00116       {
00117         if (m_counts) m_counts->acquire_weak();
00118         else          m_master->incr_ref_count();
00119       }
00120   }
00121 
00122   void release() const throw()
00123   {
00124     if (m_master)
00125       {
00126         if (m_counts) m_counts->release_weak();
00127         else          m_master->decr_ref_count();
00128       }
00129 
00130     m_counts = 0; m_master = 0;
00131   }
00132 
00133   void ensure_valid() const
00134   {
00135     if (!is_valid())
00136       nub::detail::throw_soft_ref_invalid(typeid(T), SRC_POS);
00137   }
00138 
00139   void swap(weak_handle& other) throw()
00140   {
00141     rutz::swap2(m_master, other.m_master);
00142     rutz::swap2(m_counts, other.m_counts);
00143   }
00144 
00145   // In order to avoid storing a separate bool indicating whether we
00146   // are using strong or weak refs, we use the following convention:
00147   // if we are strong ref-counting, then m_counts stays null, but if
00148   // we are weak ref-counting, then m_counts will be non-null.
00149 
00150   mutable T* m_master;
00151   mutable nub::ref_counts* m_counts;
00152 };
00153 
00154 static const char __attribute__((used)) vcid_groovx_nub_weak_handle_h_utc20051116165018[] = "$Id: weak_handle.h 10065 2007-04-12 05:54:56Z rjpeters $ $HeadURL: file:
00155 #endif // !GROOVX_NUB_WEAK_HANDLE_H_UTC20051116165018DEFINED

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