00001 /* 00002 * Copyright (c) 2000, 2020, Oracle and/or its affiliates. 00003 * 00004 * Licensed under the Universal Permissive License v 1.0 as shown at 00005 * http://oss.oracle.com/licenses/upl. 00006 */ 00007 #ifndef COH_WEAK_HANDLE_HPP 00008 #define COH_WEAK_HANDLE_HPP 00009 00010 #include "coherence/lang/compatibility.hpp" 00011 00012 #include "coherence/lang/MemberHandle.hpp" 00013 #include "coherence/lang/Object.hpp" 00014 #include "coherence/lang/TypedHandle.hpp" 00015 #include "coherence/lang/TypedHolder.hpp" 00016 #include "coherence/lang/WeakReference.hpp" 00017 00018 #include <ostream> 00019 00020 COH_OPEN_NAMESPACE2(coherence,lang) 00021 00022 00023 /** 00024 * WeakHandles are a TypedHandle like wrapper around WeakReferences. 00025 * WeakReferences allow one Object to safely reference another without blocking 00026 * it from being destroyed. WeakReferences are necessary when building Object 00027 * graphs to avoid leaking the Object graph due to cyclic references. 00028 * 00029 * WeakReferences are automatically NULL'd out when their referenced Object 00030 * is destroyed. Additionally if the weakly referenced Object becomes only 00031 * referenced via Views, then the WeakReference and corresponding WeakHandle 00032 * will only return View to the Object, if an attempt is made to obtain a 00033 * Handle a NULL will be returned instead. 00034 * 00035 * WeakHandles behave like MemberHandles by transferring their constness to 00036 * their referenced Object. As with MemberHandle WeakHandles are a thread-safe 00037 * handle implementation. As such they require references to both the 00038 * referenced "child" Object, as well as the owning "parent" Object. As with 00039 * MemberView the parent object must inherit from Object. 00040 * 00041 * If the weakly referenced Object will always be referenced as a View then 00042 * using the WeakView class would be more appropriate 00043 * 00044 * Note: In the rare case that a WeakHandle is declared via the mutable 00045 * keyword, the WeakHandle must be informed of this fact by setting 00046 * fMutable to true during construction. 00047 * 00048 * @see MemberHandle 00049 * @see WeakView 00050 * 00051 * @author mf 2007.07.05 00052 */ 00053 template<class T> 00054 class WeakHandle 00055 { 00056 // ----- typedefs ------------------------------------------------------- 00057 00058 public: 00059 /** 00060 * The type of Object which this handle weakly references. 00061 */ 00062 typedef T ValueType; 00063 00064 /** 00065 * The associated non-weak Handle type. 00066 */ 00067 typedef typename T::Handle ValueHandle; 00068 00069 /** 00070 * The associated non-weak View type. 00071 */ 00072 typedef typename T::View ValueView; 00073 00074 /** 00075 * The MemberHandle used to hold the internal WeakReference. 00076 */ 00077 typedef MemberHandle<WeakReference> InnerHandle; 00078 00079 /** 00080 * Result type for a non-const get operation. 00081 */ 00082 typedef ValueHandle GetType; 00083 00084 /** 00085 * Result type for a non-const get operation. 00086 */ 00087 typedef ValueView ConstGetType; 00088 00089 00090 // ----- constructors --------------------------------------------------- 00091 00092 public: 00093 /** 00094 * Default constructor. 00095 */ 00096 WeakHandle(const Object& oGuardian) 00097 : m_hWeak(oGuardian), m_pWeak(NULL) 00098 { 00099 } 00100 00101 /** 00102 * Construct a WeakHandle from a normal Handle. 00103 * 00104 * @param oGuardian the self() on the object this data member is a 00105 * member of 00106 * @param that the object to reference 00107 */ 00108 WeakHandle(const Object& oGuardian, const TypedHandle<T>& that) 00109 : m_hWeak(oGuardian, NULL == that ? NULL : that->_attachWeak()), 00110 m_pWeak(get_pointer(that)) 00111 { 00112 } 00113 00114 /** 00115 * Construct a WeakHandle from a normal Handle. 00116 * 00117 * @param oGuardian the self() on the object this data member is a 00118 * member of 00119 * @param that the object to reference 00120 * @param fMutable true if the member is declared as mutable, false 00121 * if declared as const 00122 */ 00123 WeakHandle(const Object& oGuardian, const TypedHandle<T>& that, bool fMutable) 00124 : m_hWeak(oGuardian, NULL == that ? NULL : that->_attachWeak(), 00125 fMutable), 00126 m_pWeak(get_pointer(that)) 00127 { 00128 } 00129 00130 private: 00131 /** 00132 * Blocked copy constructor. 00133 */ 00134 WeakHandle(const WeakHandle& wh); 00135 00136 00137 // ----- operators ------------------------------------------------------ 00138 00139 public: 00140 /** 00141 * Re-assign the WeakHandle to weakly reference a new Object. 00142 * 00143 * @param that the object to reference 00144 */ 00145 WeakHandle& operator=(const TypedHandle<T>& that) 00146 { 00147 T* pThat = get_pointer(that); 00148 WeakReference::Handle hRef = NULL == that 00149 ? WeakReference::Handle(NULL) 00150 : that->_attachWeak(); 00151 00152 // update m_hWeak and m_pWeak under a single write lock 00153 { 00154 SynchronizedMemberWriteBlock guard(get_guardian(m_hWeak)); 00155 guard.setMember(m_hWeak, hRef); 00156 m_pWeak = pThat; 00157 } 00158 00159 return *this; 00160 } 00161 00162 /** 00163 * Assign this WeakHandle to reference the same Object as the specified 00164 * WeakHandle. 00165 * 00166 * @param that the object to reference 00167 * 00168 * @return a reference to this MemberHandle 00169 */ 00170 WeakHandle& operator=(WeakHandle& that) 00171 { 00172 return operator=((ValueHandle) that); // assign from snapshot 00173 } 00174 00175 /** 00176 * Return a non-weak Handle to the weakly referenced Object, or a 00177 * Handle to NULL if the weakly referenced Object has been destroyed 00178 * or is now only referenced via Views. 00179 * 00180 * @return ValueHandle 00181 */ 00182 operator ValueHandle() 00183 { 00184 WeakReference::Handle hRef; 00185 T* pWeak; 00186 00187 // read m_hWeak and m_pWeak under a single read lock 00188 { 00189 SynchronizedMemberReadBlock guard(get_guardian(m_hWeak)); 00190 hRef = guard.getMember(m_hWeak); 00191 pWeak = m_pWeak; 00192 } 00193 00194 if (NULL == hRef) 00195 { 00196 return NULL; 00197 } 00198 00199 // utilize pWeak to avoid cost of dynamic cast 00200 Object::Handle h = cast<Object::Handle>(hRef->get(), 00201 /*fThrow*/ false); 00202 return NULL == h 00203 ? TypedHandle<T>() 00204 : TypedHandle<T>(pWeak, h); 00205 } 00206 00207 /** 00208 * Return a non-weak View to the weakly referenced Object, or a 00209 * Handle to NULL if the weakly referenced Object has been 00210 * destroyed. 00211 * 00212 * @return ValueHandle 00213 */ 00214 operator ValueView() const 00215 { 00216 WeakReference::View vRef; 00217 const T* cpWeak; 00218 00219 // read m_hWeak and m_pWeak under a single read lock 00220 { 00221 SynchronizedMemberReadBlock guard(get_guardian(m_hWeak)); 00222 vRef = guard.getMember(m_hWeak); 00223 cpWeak = m_pWeak; 00224 } 00225 00226 if (NULL == vRef) 00227 { 00228 return NULL; 00229 } 00230 00231 // utilize cpWeak to avoid cost of dynamic cast 00232 Object::View v = vRef->get(); 00233 return NULL == v 00234 ? TypedHandle<const T>() 00235 : TypedHandle<const T>(cpWeak, v); 00236 } 00237 00238 /** 00239 * Return a View to the referenced Object. 00240 * 00241 * @return a View to the referenced Object 00242 */ 00243 template<class PT> 00244 operator TypedHandle<const PT>() const 00245 { 00246 return (ValueView) *this; 00247 } 00248 00249 /** 00250 * Return a Handle to the referenced Object. 00251 * 00252 * @return a Handle to the referenced Object 00253 */ 00254 template<class PT> 00255 operator TypedHandle<PT>() 00256 { 00257 return (ValueHandle) *this; 00258 } 00259 00260 /** 00261 * Return a TypedHolder to the referenced Object. 00262 * 00263 * @return a TypedHolder to the referenced Object 00264 * 00265 */ 00266 template<class PT> 00267 operator TypedHolder<PT>() const 00268 { 00269 return (ValueView) *this; 00270 } 00271 00272 /** 00273 * Return a TypedHolder to the referenced Object. 00274 * 00275 * @return a TypedHolder to the referenced Object 00276 */ 00277 template<class PT> 00278 operator TypedHolder<PT>() 00279 { 00280 return (ValueHandle) *this; 00281 } 00282 00283 /** 00284 * Dereference the WeakHandle returning a non-weak Handle. 00285 * 00286 * If the non-weak Handle is non-NULL then it is guaranteed 00287 * that the Object will continue to exist for at least the 00288 * life of the returned handle. 00289 * 00290 * @return ValueHandle 00291 */ 00292 ValueHandle operator->() 00293 { 00294 return (ValueHandle) *this; 00295 } 00296 00297 /** 00298 * Dereference the WeakHandle returning a non-weak View. 00299 * 00300 * If the non-weak Handle is non-NULL then it is guaranteed 00301 * that the Object will continue to exist for at least the 00302 * life of the returned View. 00303 * 00304 * @return ValueHandle 00305 */ 00306 ValueView operator->() const 00307 { 00308 return (ValueView) *this; 00309 } 00310 00311 /** 00312 * Dereference this handle, returning <tt>T&</tt>. 00313 * 00314 * @return a raw <tt>T&</tt> reference to the referenced Object 00315 * 00316 * @throws NullPointerException if the this handle is @c NULL 00317 */ 00318 const T& operator*() const 00319 { 00320 return *operator->(); 00321 } 00322 00323 /** 00324 * Dereference this handle, returning <tt>T&</tt>. 00325 * 00326 * @return a raw <tt>T&</tt> reference to the referenced Object 00327 * 00328 * @throws NullPointerException if the this handle is @c NULL 00329 */ 00330 T& operator*() 00331 { 00332 return *operator->(); 00333 } 00334 00335 private: 00336 /** 00337 * Blocked assignment operator. 00338 */ 00339 WeakHandle<T>& operator=(const WeakHandle<T>&); 00340 00341 00342 // ----- data members --------------------------------------------------- 00343 00344 protected: 00345 /** 00346 * The Handle to the associated WeakReference. 00347 */ 00348 InnerHandle m_hWeak; 00349 00350 /** 00351 * Raw pointer to the weakly referenced object. 00352 */ 00353 T* m_pWeak; 00354 }; 00355 00356 00357 // ----- non-member operators and functions --------------------------------- 00358 00359 /** 00360 * Output a human-readable description of the given WeakHandle<T> to the 00361 * specified stream. 00362 * 00363 * @param out the stream used to output the description 00364 * @param wh the WeakHandle<T> to describe 00365 * 00366 * @return the supplied stream 00367 */ 00368 template <typename Char, typename Traits, class T> 00369 COH_INLINE std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& out, const WeakHandle<T>& wh) 00370 { 00371 typename WeakHandle<T>::ValueView v = wh; 00372 out << v; 00373 return out; 00374 } 00375 00376 /** 00377 * Assign the specified handle to NULL. 00378 * 00379 * @param wh the handle to clear 00380 */ 00381 template<class T> void clear_handle(WeakHandle<T>& wh) 00382 { 00383 wh = NULL; 00384 } 00385 00386 /** 00387 * Return true if the supplied handle equals NULL. 00388 * 00389 * @param wh the weak handle to test 00390 * 00391 * @return true iff the supplied handle equals NULL 00392 */ 00393 template<class T> 00394 bool is_null(const WeakHandle<T>& wh) 00395 { 00396 return wh == NULL; 00397 } 00398 00399 /** 00400 * Perform a dynamic cast the pointer associated with the WeakHandle 00401 * to a the specified handle/view type. 00402 * 00403 * @param wh the WeakHandle from which to perform the cast 00404 * @param fTest true for instanceof style test 00405 * 00406 * @return the casted pointer, or NULL if the cast fails and fTest is true 00407 * 00408 * @throws ClassCastException if the cast fails and fTest of is false 00409 */ 00410 template<class D, class T> 00411 D cast(WeakHandle<T>& wh, bool fTest = false) 00412 { 00413 return cast<D>((typename WeakHandle<T>::ValueHandle) wh, fTest); 00414 } 00415 00416 /** 00417 * Perform a dynamic cast the pointer associated with the WeakHandle 00418 * to a the specified handle/view type. 00419 * 00420 * @param wh the WeakHandle from which to perform the cast 00421 * @param fThrow true if an exception is to be thrown on a failed cast 00422 * 00423 * @return the casted pointer, or NULL if the cast fails and fThrow is false 00424 * 00425 * @throws ClassCastException if the cast fails and fThrow is true 00426 */ 00427 template<class D, class T> 00428 D cast(const WeakHandle<T>& wh, bool fThrow = true) 00429 { 00430 return cast<D>((typename WeakHandle<T>::ValueHandle) wh, fThrow); 00431 } 00432 00433 /** 00434 * Perform an instanceof check on a handle or view. 00435 * 00436 * @param wh the WeakHandle from which to perform the test 00437 * 00438 * @return true if the supplied handle is an instance of the specified type 00439 */ 00440 template<class D, class T> 00441 bool instanceof(const WeakHandle<T>& wh) 00442 { 00443 return NULL != cast<D>(wh, false); 00444 } 00445 00446 /** 00447 * Perform an instanceof check on a handle or view. 00448 * 00449 * @param wh the WeakHandle from which to perform the test 00450 * 00451 * @return true if the supplied handle is an instance of the specified type 00452 */ 00453 template<class D, class T> 00454 bool instanceof(WeakHandle<T>& wh) 00455 { 00456 return NULL != cast<D>(wh, false); 00457 } 00458 00459 COH_CLOSE_NAMESPACE2 00460 00461 #endif // COH_WEAK_HANDLE_HPP