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