00001 /* 00002 * WeakHolder.hpp 00003 * 00004 * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. 00005 * 00006 * Oracle is a registered trademarks of Oracle Corporation and/or its 00007 * affiliates. 00008 * 00009 * This software is the confidential and proprietary information of Oracle 00010 * Corporation. You shall not disclose such confidential and proprietary 00011 * information and shall use it only in accordance with the terms of the 00012 * license agreement you entered into with Oracle. 00013 * 00014 * This notice may not be removed or altered. 00015 */ 00016 #ifndef COH_WEAK_HOLDER_HPP 00017 #define COH_WEAK_HOLDER_HPP 00018 00019 #include "coherence/lang/compatibility.hpp" 00020 00021 #include "coherence/lang/Object.hpp" 00022 #include "coherence/lang/TypedHandle.hpp" 00023 #include "coherence/lang/TypedHolder.hpp" 00024 #include "coherence/lang/MemberHolder.hpp" 00025 #include "coherence/lang/WeakReference.hpp" 00026 00027 COH_OPEN_NAMESPACE2(coherence,lang) 00028 00029 00030 /** 00031 * WeakHolders are a TypedHolder like wrapper around WeakReferences. 00032 * WeakReferences allow one Object to safely reference another without blocking 00033 * it from being destroyed. WeakRefereces are necessary when building Object 00034 * graphs to avoid leaking the Object graph due to cyclical references. 00035 * 00036 * WeakReferences are automatically NULL'd out when their referenced Object 00037 * is destroyed. Additionally if the weakly referenced Object becomes only 00038 * referenced via Views, then the WeakReference and corresponding WeakHandle 00039 * will only return View to the Object, if an attempt is made to obtain a 00040 * Handle a NULL will be returned instead. 00041 * 00042 * WeakHolders are wrappers for MemberHolder, and provide a thread-safe handle 00043 * implementation. As such they require references to both the referenced 00044 * "child" Object, as well as the owning "parent" Object. As with MemberHolder 00045 * the parent object must inherit from Object. 00046 * 00047 * Note: In the rare case that a WeakHolder is declared via the mutable 00048 * keyword, the WeakHolder must be informed of this fact by setting 00049 * fMutable to true during construction. 00050 * 00051 * @see MemberHolder 00052 * 00053 * @author mf 2008.12.09 00054 */ 00055 template<class T> 00056 class WeakHolder 00057 { 00058 // ----- typedefs ------------------------------------------------------- 00059 00060 public: 00061 /** 00062 * The type of Object which this handle weakly references. 00063 */ 00064 typedef const T ValueType; 00065 00066 /** 00067 * The associated non-weak Handle type. 00068 */ 00069 typedef typename T::Handle ValueHandle; 00070 00071 /** 00072 * The associated non-weak View type. 00073 */ 00074 typedef typename T::View ValueView; 00075 00076 /** 00077 * The associated non-weak Holder type. 00078 */ 00079 typedef typename T::Holder ValueHolder; 00080 00081 00082 // ----- constructors --------------------------------------------------- 00083 00084 public: 00085 /** 00086 * Construct a WeakHolder referencing NULL. 00087 * 00088 * @param oGuardian reference to the WeakHolder's parent 00089 */ 00090 WeakHolder(const Object& oGuardian) 00091 : m_ohWeak(oGuardian, WeakReference::valueOf(NULL)), 00092 m_cpWeak(NULL) 00093 { 00094 } 00095 00096 /** 00097 * Construct a WeakHolder referencing an object. 00098 * 00099 * @param oGuardian reference to the WeakHolder's parent 00100 * @param that the object to reference 00101 */ 00102 WeakHolder(const Object& oGuardian, const TypedHolder<T>& that) 00103 : m_ohWeak(oGuardian, WeakReference::valueOf(that)), 00104 m_cpWeak(get_pointer(that)) 00105 { 00106 } 00107 00108 /** 00109 * Construct a WeakHolder referencing an object. 00110 * 00111 * @param oGuardian reference to the WeakHolder's parent 00112 * @param that the object to reference 00113 * @param fMutable true if the member is declared as mutable, false 00114 * if declared as const 00115 */ 00116 WeakHolder(const Object& oGuardian, const TypedHolder<T>& that, 00117 bool fMutable) 00118 : m_ohWeak(oGuardian, WeakReference::valueOf(that), fMutable), 00119 m_cpWeak(get_pointer(that)) 00120 { 00121 } 00122 00123 00124 // ----- operators ------------------------------------------------------ 00125 00126 public: 00127 /** 00128 * Re-assign the WeakHolder to weakly reference a new Object. 00129 * 00130 * @param that the object to reference 00131 */ 00132 WeakHolder& operator=(const TypedHolder<T>& that) 00133 { 00134 WeakReference::Holder ohRef = WeakReference::valueOf(that); 00135 const T* cpThat = get_pointer(that); 00136 00137 // update m_ohWeak and m_cpWeak under a single write lock 00138 { 00139 SynchronizedMemberWriteBlock guard(get_guardian(m_ohWeak)); 00140 guard.setMember(m_ohWeak, ohRef); 00141 m_cpWeak = cpThat; 00142 } 00143 00144 return *this; 00145 } 00146 00147 /** 00148 * Re-assign the WeakHolder to weakly reference a new Object. 00149 * 00150 * @param that the object to reference 00151 */ 00152 WeakHolder& operator=(const WeakHolder& that) 00153 { 00154 return operator=((ValueHolder) that); 00155 } 00156 00157 /** 00158 * Return a non-weak View to the weakly referenced Object, or a 00159 * View to NULL if the weakly referenced Object has been 00160 * destroyed. 00161 * 00162 * @return ValueView 00163 */ 00164 operator ValueView() const 00165 { 00166 WeakReference::View vRef; 00167 const T* cpWeak; 00168 00169 // read m_ohWeak and m_cpWeak under a single read lock 00170 { 00171 SynchronizedMemberReadBlock guard(get_guardian(m_ohWeak)); 00172 vRef = guard.getMember(m_ohWeak); 00173 cpWeak = m_cpWeak; 00174 } 00175 00176 Object::View v = vRef->get(); 00177 return NULL == v 00178 ? TypedHandle<const T>() // Object has been collected 00179 : TypedHandle<const T>(cpWeak, v); 00180 } 00181 00182 /** 00183 * Return a View to the referenced Object. 00184 * 00185 * @return a View to the referenced Object 00186 */ 00187 template<class PT> 00188 operator TypedHandle<const PT>() const 00189 { 00190 return (ValueView) *this; 00191 } 00192 00193 /** 00194 * Return a TypedHolder to the referenced Object. 00195 * 00196 * @return a TypedHolder to the referenced Object 00197 */ 00198 template<class PT> 00199 operator TypedHolder<PT>() const 00200 { 00201 WeakReference::Holder ohRef; 00202 const T* cpWeak; 00203 00204 // read m_hWeak and m_pWeak under a single read lock 00205 { 00206 SynchronizedMemberReadBlock guard(get_guardian(m_ohWeak)); 00207 ohRef = guard.getMember(m_ohWeak); 00208 cpWeak = m_cpWeak; 00209 } 00210 00211 WeakReference::Handle hRef = cast<WeakReference::Handle>(ohRef, 00212 /*fThrow*/ false); 00213 Object::Holder oh = NULL == hRef 00214 ? ohRef->get() 00215 : hRef->get(); 00216 00217 if (NULL == oh) 00218 { 00219 return NULL; // Object has been collected 00220 } 00221 else if (NULL == hRef) 00222 { 00223 return TypedHandle<const T>(cpWeak, oh); // View 00224 } 00225 else 00226 { 00227 return TypedHandle<T>(const_cast<T*>(cpWeak), oh); // Handle 00228 } 00229 } 00230 00231 /** 00232 * Dereference the WeakHolder returning a non-weak View. 00233 * 00234 * If the non-weak View is non-NULL then it is guaranteed 00235 * that the Object will continue to exist for at least the 00236 * life of the returned View. 00237 * 00238 * @return a non-weak View to the referenced Object 00239 */ 00240 ValueView operator->() const 00241 { 00242 return (ValueView) *this; 00243 } 00244 00245 /** 00246 * Dereference this handle, returning <tt>T&</tt>. 00247 * 00248 * @return a raw <tt>T&</tt> reference to the referenced Object 00249 * 00250 * @throws NullPointerException if the this handle is @c NULL 00251 */ 00252 const T& operator*() const 00253 { 00254 return *operator->(); 00255 } 00256 00257 // ----- data members --------------------------------------------------- 00258 00259 protected: 00260 /** 00261 * The Holder to the associated WeakReference. 00262 */ 00263 MemberHolder<WeakReference> m_ohWeak; 00264 00265 /** 00266 * Raw pointer to the weakly referenced object. 00267 */ 00268 const T* m_cpWeak; 00269 }; 00270 00271 00272 // ----- non-member operators and functions --------------------------------- 00273 00274 /** 00275 * Output a human-readable description of the given 00276 * WeakHolder<T> to the specified stream. 00277 * 00278 * @param out the stream used to output the description 00279 * @param woh the WeakHolder<T> to describe 00280 * 00281 * @return the supplied stream 00282 */ 00283 template<class T> 00284 std::ostream& operator<<(std::ostream& out, const WeakHolder<T>& woh) 00285 { 00286 typename WeakHolder<T>::ValueView v = woh; 00287 out << v; 00288 return out; 00289 } 00290 00291 /** 00292 * Assign the specified handle to NULL. 00293 * 00294 * @param woh the handle to clear 00295 */ 00296 template<class T> void clear_handle(WeakHolder<T>& woh) 00297 { 00298 woh = NULL; 00299 } 00300 00301 /** 00302 * Return true if the supplied handle equals NULL. 00303 * 00304 * @param woh the weak handle to test 00305 * 00306 * @return true iff the supplied handle equals NULL 00307 */ 00308 template<class T> 00309 bool is_null(const WeakHolder<T>& woh) 00310 { 00311 return woh == NULL; 00312 } 00313 00314 /** 00315 * Perform a dynamic cast the pointer associated with the WeakHolder 00316 * to a the specified handle/view type. 00317 * 00318 * @param woh the WeakHolder from which to perform the cast 00319 * @param fThrow true if an exception is to be thrown on a failed cast 00320 * 00321 * @return the casted pointer, or NULL if the cast fails and fThrow is false 00322 * 00323 * @throws ClassCastException if the cast fails and fThrow is true 00324 */ 00325 template<class D, class T> 00326 D cast(const WeakHolder<T>& woh, bool fThrow = true) 00327 { 00328 return cast<D>((TypedHolder<T>) woh, fThrow); 00329 } 00330 00331 /** 00332 * Perform an instanceof check on a handle or view. 00333 * 00334 * @param woh the WeakHolder from which to perform the test 00335 * 00336 * @return true if the supplied handle is an instance of the specified type 00337 */ 00338 template<class D, class T> 00339 bool instanceof(const WeakHolder<T>& woh) 00340 { 00341 return NULL != cast<D>(woh, false); 00342 } 00343 00344 COH_CLOSE_NAMESPACE2 00345 00346 #endif // COH_WEAK_HOLDER_HPP