00001
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
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"
00041 #include "rutz/fileposition.h"
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)
00095 {
00096 return (m_master != 0);
00097 }
00098
00099
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
00146
00147
00148
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