Oracle Coherence for C++ API
Release 3.7.1.0
E22845-01
00001 /* 00002 * MemberHandle.hpp 00003 * 00004 * Copyright (c) 2000, 2011, 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_MEMBER_HANDLE_HPP 00017 #define COH_MEMBER_HANDLE_HPP 00018 00019 #include "coherence/lang/compatibility.hpp" 00020 00021 #include "coherence/lang/Object.hpp" 00022 #include "coherence/lang/SmartMember.hpp" 00023 #include "coherence/lang/SynchronizedMemberReadBlock.hpp" 00024 #include "coherence/lang/SynchronizedMemberWriteBlock.hpp" 00025 #include "coherence/lang/TypedHandle.hpp" 00026 00027 #include <ostream> 00028 #include <sstream> 00029 00030 COH_OPEN_NAMESPACE2(coherence,lang) 00031 00032 template<class> class MemberView; 00033 00034 00035 /** 00036 * MemberHandle is a thread-safe handle used by an Object to reference its 00037 * non-const child Objects. 00038 * 00039 * MemberHandles transfer the constness of their guardian Object. When a 00040 * MemberHandle is accessed from within a const method of the enclosing 00041 * "parent" class, it will only provide const access to the Object which it 00042 * references. If the enclosing Object becomes only accessed via views the 00043 * MemberHandle will also automatically, and permanently switch its reference 00044 * type from a handle to a view. 00045 * 00046 * Note: In the rare case that a MemberHandle is declared via the mutable 00047 * keyword, the MemberHandle must be informed of this fact by setting 00048 * fMutable to true during construction. 00049 * 00050 * @author mf 2007.07.05 00051 * 00052 * @see MemberView 00053 * @see MemberHolder 00054 */ 00055 template<class T> 00056 class MemberHandle 00057 : public SmartMember 00058 { 00059 // ----- typedefs ------------------------------------------------------- 00060 00061 public: 00062 /** 00063 * The type of the values the handle can reference. 00064 */ 00065 typedef T ValueType; 00066 00067 /** 00068 * The Handle type for the referenced Object. 00069 */ 00070 typedef typename T::Handle ValueHandle; 00071 00072 /** 00073 * The View type for the referenced Object. 00074 */ 00075 typedef typename T::View ValueView; 00076 00077 /** 00078 * Result type for a non-const get operation. 00079 */ 00080 typedef ValueHandle GetType; 00081 00082 /** 00083 * Result type for a non-const get operation. 00084 */ 00085 typedef ValueView ConstGetType; 00086 00087 00088 // -------- constructors ------------------------------------------------ 00089 00090 public: 00091 /** 00092 * Construct a new MemberHandle referencing NULL via a handle. 00093 * 00094 * @param oGuardian the object that protects this member 00095 */ 00096 MemberHandle(const Object& oGuardian) 00097 : SmartMember(oGuardian), m_po(NULL) 00098 { 00099 } 00100 00101 /** 00102 * Construct a new MemberHandle referencing the specified Object via 00103 * a handle. 00104 * 00105 * @param oGuardian the object that protects this member 00106 * @param that the Object to reference 00107 */ 00108 MemberHandle(const Object& oGuardian, const ValueHandle& that) 00109 : SmartMember(oGuardian), 00110 m_po(NULL) 00111 { 00112 T* po = get_pointer(that); 00113 if (po != NULL) 00114 { 00115 po->_attach(oGuardian._isEscaped()); 00116 m_po = po; 00117 } 00118 } 00119 00120 /** 00121 * Construct a new MemberHandle referencing the specified Object via 00122 * a handle. 00123 * 00124 * @param oGuardian the object that protects this member 00125 * @param that the Object to reference 00126 * @param fMutable true if the member is declared as mutable, false 00127 * if declared as const 00128 */ 00129 MemberHandle(const Object& oGuardian, const ValueHandle& that, 00130 bool fMutable) 00131 : SmartMember(oGuardian, fMutable ? forever_mutable : safe_immutable), 00132 m_po(NULL) 00133 { 00134 T* po = get_pointer(that); 00135 if (po != NULL) 00136 { 00137 if (fMutable) 00138 { 00139 po->_attach(oGuardian._isEscaped()); 00140 } 00141 else 00142 { 00143 ((const T*) po)->_attach(oGuardian._isEscaped()); 00144 } 00145 m_po = po; 00146 } 00147 } 00148 00149 /** 00150 * Destroy the MemberHandle. 00151 */ 00152 ~MemberHandle() 00153 { 00154 T* po = m_po; 00155 Mutability nMutability = m_nMutability; 00156 00157 if (NULL != po) 00158 { 00159 m_po = NULL; 00160 try 00161 { 00162 bool fEscaped = getGuardian()._isEscaped(); 00163 if (nMutability >= forever_immutable) 00164 { 00165 ((const T*) po)->_detach(fEscaped); 00166 } 00167 else 00168 { 00169 po->_detach(fEscaped); 00170 } 00171 } 00172 catch (const std::exception& e) 00173 { 00174 // Exception::View is not a known type within this file 00175 std::cerr << "Error during ~MemberHandle: " << e.what() << std::endl; 00176 return; // can't re-throw from within destructor 00177 } 00178 } 00179 } 00180 00181 private: 00182 /** 00183 * Blocked copy constructor. 00184 */ 00185 MemberHandle(const MemberHandle&); 00186 00187 00188 // ----- operators ------------------------------------------------------ 00189 00190 public: 00191 /** 00192 * Assign the MemberHandle to reference another object. 00193 * 00194 * @param that the object to reference 00195 * 00196 * @return a reference to this MemberHandle 00197 */ 00198 MemberHandle& operator=(const ValueHandle& that) 00199 { 00200 set(that); 00201 return *this; 00202 } 00203 00204 /** 00205 * Assign this MemberHandle to reference the same Object as the 00206 * specified MemberHandle. 00207 * 00208 * @param that the object to reference 00209 * 00210 * @return a reference to this MemberHandle 00211 */ 00212 MemberHandle& operator=(MemberHandle& that) 00213 { 00214 operator=((ValueHandle) that); // assign from snapshot 00215 return *this; 00216 } 00217 00218 /** 00219 * Return a View to the referenced Object. 00220 * 00221 * @return a View to the referenced Object 00222 */ 00223 operator ValueView() const 00224 { 00225 return get(); 00226 } 00227 00228 /** 00229 * Return a Handle to the referenced Object. 00230 * 00231 * @return a Handle to the referenced Object 00232 */ 00233 operator ValueHandle() 00234 { 00235 return get(); 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 get(); 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 get(); 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 get(); 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 get(); 00281 } 00282 00283 /** 00284 * Dereference the MemberHandle. 00285 * 00286 * @return a const pointer to the referenced Object 00287 */ 00288 ValueView operator->() const 00289 { 00290 return get(); 00291 } 00292 00293 /** 00294 * Dereference the MemberHandle. 00295 * 00296 * @return a const pointer to the referenced Object 00297 */ 00298 ValueHandle operator->() 00299 { 00300 return get(); 00301 } 00302 00303 /** 00304 * Dereference this handle, returning <tt>T&</tt>. 00305 * 00306 * @return a raw <tt>T&</tt> reference to the referenced Object 00307 * 00308 * @throws NullPointerException if the this handle is @c NULL 00309 */ 00310 const T& operator*() const 00311 { 00312 return *get(); 00313 } 00314 00315 /** 00316 * Dereference this handle, returning <tt>T&</tt>. 00317 * 00318 * @return a raw <tt>T&</tt> reference to the referenced Object 00319 * 00320 * @throws NullPointerException if the this handle is @c NULL 00321 */ 00322 T& operator*() 00323 { 00324 return *get(); 00325 } 00326 00327 private: 00328 /** 00329 * Blocked assignment operator. 00330 */ 00331 MemberHandle<T>& operator=(const MemberHandle<T>&); 00332 00333 00334 // ----- helper methods ------------------------------------------------- 00335 00336 protected: 00337 /** 00338 * Set the MemberHandle to reference the same Object as the supplied 00339 * Handle. 00340 * 00341 * @param that the handle to copy 00342 * @param pSync optional external SyncornizedMemberBlock to use 00343 * to avoid internal synchronization. 00344 */ 00345 void set(const TypedHandle<T>& that, 00346 SynchronizedMemberWriteBlock* pSync = NULL) 00347 { 00348 const Object& oGuardian = getGuardian(); 00349 T* po = get_pointer(that); 00350 T* pDetach = NULL; 00351 bool fEscaped = oGuardian._isEscaped(); 00352 Object* pAttach = po == NULL ? NULL : po->_attach(fEscaped); 00353 00354 if (pSync != NULL) 00355 { 00356 // sync block 00357 SynchronizedMemberWriteBlock syncWrite(oGuardian, pSync); 00358 if (m_nMutability >= forever_immutable) 00359 { 00360 coh_throw_illegal_state("attempt to set const MemberHandle"); 00361 } 00362 pDetach = m_po; 00363 m_po = NULL == pAttach ? NULL : po; 00364 } 00365 else if (fEscaped) 00366 { 00367 // sync block 00368 SynchronizedMemberWriteBlock::Guard guard(oGuardian); 00369 if (m_nMutability >= forever_immutable) 00370 { 00371 coh_throw_illegal_state("attempt to set const MemberHandle"); 00372 } 00373 pDetach = m_po; 00374 m_po = NULL == pAttach ? NULL : po; 00375 } 00376 else 00377 { 00378 if (m_nMutability >= forever_immutable) 00379 { 00380 coh_throw_illegal_state("attempt to set const MemberHandle"); 00381 } 00382 pDetach = m_po; 00383 m_po = NULL == pAttach ? NULL : po; 00384 } 00385 00386 if (pDetach) 00387 { 00388 pDetach->_detach(fEscaped); 00389 } 00390 } 00391 00392 /** 00393 * Return a View to the referenced Object. 00394 * 00395 * @param pSync optional external SyncornizedMemberReadBlock to use 00396 * to avoid internal synchronization. 00397 * 00398 * @return a View to the referenced Object 00399 */ 00400 ValueView get(SynchronizedMemberReadBlock* pSync = NULL) const 00401 { 00402 const Object& oGuardian = getGuardian(); 00403 if (pSync != NULL) 00404 { 00405 SynchronizedMemberReadBlock syncRead(oGuardian, pSync); 00406 // return of escaped must occur within scope of syncRead 00407 return ValueView((const T*) m_po); 00408 } 00409 else if (m_nMutability == safe_immutable || !oGuardian._isEscaped()) 00410 { 00411 // non-escaped, or safe_immutable, synchronization not required 00412 return ValueView((const T*) m_po); 00413 } 00414 else 00415 { 00416 SynchronizedMemberReadBlock::Guard guard(oGuardian); 00417 // return of escaped must occur within scope of guard 00418 return ValueView((const T*) m_po); 00419 } 00420 } 00421 00422 /** 00423 * Return a Handle to the referenced Object. 00424 * 00425 * @param pSync optional external SyncornizedMemberReadBlock to use 00426 * to avoid internal synchronization. 00427 * 00428 * @return a Handle to the referenced Object 00429 */ 00430 ValueHandle get(SynchronizedMemberReadBlock* pSync = NULL) 00431 { 00432 const Object& oGuardian = getGuardian(); 00433 if (pSync != NULL) 00434 { 00435 SynchronizedMemberReadBlock syncRead(oGuardian, pSync); 00436 if (m_nMutability >= forever_immutable) 00437 { 00438 coh_throw_illegal_state( 00439 "attempt to access handle from const MemberHandle"); 00440 } 00441 return m_po; // must occur within scope of syncRead 00442 } 00443 else if (oGuardian._isEscaped()) 00444 { 00445 SynchronizedMemberReadBlock::Guard guard(oGuardian); 00446 if (m_nMutability >= forever_immutable) 00447 { 00448 coh_throw_illegal_state( 00449 "attempt to access handle from const MemberHandle"); 00450 } 00451 return m_po; // must occur within scope of syncRead 00452 } 00453 00454 if (m_nMutability >= forever_immutable) 00455 { 00456 coh_throw_illegal_state( 00457 "attempt to access handle from const MemberHandle"); 00458 } 00459 return m_po; 00460 } 00461 00462 00463 // ----- SmartMember interface ------------------------------------------ 00464 00465 protected: 00466 /** 00467 * {@inheritDoc} 00468 * 00469 * The MemberHandle is automatically flipped when the guardian Object 00470 * becomes only referenced via consts. 00471 */ 00472 virtual void onConst() 00473 { 00474 const Object& oGuardian = getGuardian(); 00475 bool fEscaped = oGuardian._isEscaped(); 00476 T* po = NULL; 00477 00478 if (fEscaped) 00479 { 00480 SynchronizedMemberWriteBlock::Guard guard(oGuardian); 00481 po = m_po; 00482 } 00483 else 00484 { 00485 po = m_po; 00486 } 00487 00488 if (NULL != po) 00489 { 00490 // re-attach as const, then detach the old reference 00491 ((const T*) po)->_attach(fEscaped); 00492 po->_detach(fEscaped); 00493 } 00494 00495 SmartMember::onConst(); 00496 } 00497 00498 /** 00499 * {@inheritDoc} 00500 */ 00501 virtual void onEscape(bool fEscaped) const 00502 { 00503 T* po = m_po; 00504 if (po != NULL) 00505 { 00506 if (m_nMutability >= forever_immutable) 00507 { 00508 const T* cpo = po; 00509 cpo->_attach(fEscaped); // new attach 00510 cpo->_detach(!fEscaped); // old detach 00511 } 00512 else 00513 { 00514 po->_attach(fEscaped); // new attach 00515 po->_detach(!fEscaped); // old detach 00516 } 00517 } 00518 00519 SmartMember::onEscape(fEscaped); 00520 } 00521 00522 00523 // ----- data members --------------------------------------------------- 00524 00525 protected: 00526 /** 00527 * The referenced Object. 00528 */ 00529 T* m_po; 00530 00531 00532 // ----- friends -------------------------------------------------------- 00533 00534 /** 00535 * @internal 00536 */ 00537 template<class D, class H> friend D cast(MemberHandle<T>& mh, bool fThrow); 00538 00539 /** 00540 * @internal 00541 */ 00542 friend class SynchronizedMemberReadBlock; 00543 00544 /** 00545 * @internal 00546 */ 00547 friend class SynchronizedMemberWriteBlock; 00548 }; 00549 00550 00551 // ----- non-member operators and functions --------------------------------- 00552 00553 /** 00554 * Output a human-readable description of the given MemberHandle to the 00555 * specified stream. 00556 * 00557 * @param out the stream used to output the description 00558 * @param mh the MemberHandle to describe 00559 * 00560 * @return the supplied stream 00561 */ 00562 template<class T> std::ostream& operator<<(std::ostream& out, const MemberHandle<T>& mh) 00563 { 00564 out << (typename T::View) mh; 00565 return out; 00566 } 00567 00568 /** 00569 * Assign the specified handle to NULL. 00570 * 00571 * @param mh the handle to clear 00572 */ 00573 template<class T> void clear_handle(MemberHandle<T>& mh) 00574 { 00575 mh = NULL; 00576 } 00577 00578 /** 00579 * Return true if the supplied handle equals NULL. 00580 * 00581 * @param mh the member handle to test 00582 * 00583 * @return true iff the supplied handle equals NULL 00584 */ 00585 template<class T> 00586 bool is_null(const MemberHandle<T>& mh) 00587 { 00588 return mh == NULL; 00589 } 00590 00591 /** 00592 * Perform a dynamic cast the pointer associated with the MemberHandle 00593 * to a the specified handle/view type. 00594 * 00595 * @param mh the MemberHandle from which to perform the cast 00596 * @param fThrow true if an exception is to be thrown on a failed cast 00597 * 00598 * @return the casted pointer, or NULL if the cast fails and fThrow is false 00599 * 00600 * @throws ClassCastException if the cast fails and fThrow is true 00601 */ 00602 template<class D, class T> 00603 D cast(MemberHandle<T>& mh, bool fThrow = true) 00604 { 00605 return cast<D>((typename MemberHandle<T>::ValueHandle) mh, fThrow); 00606 } 00607 00608 /** 00609 * Perform a dynamic cast the pointer associated with the MemberHandle 00610 * to a the specified handle/view type. 00611 * 00612 * @param mh the MemberHandle from which to perform the cast 00613 * @param fThrow true if an exception is to be thrown on a failed cast 00614 * 00615 * @return the casted pointer, or NULL if the cast fails and fThrow is false 00616 * 00617 * @throws ClassCastException if the cast fails and fThrow is true 00618 */ 00619 template<class D, class T> 00620 D cast(const MemberHandle<T>& mh, bool fThrow = true) 00621 { 00622 return cast<D>((typename MemberHandle<T>::ValueView) mh, fThrow); 00623 } 00624 00625 /** 00626 * Perform an instanceof check on a MemberHandle. 00627 * 00628 * @param mh the MemberHandle from which to perform the test 00629 * 00630 * @return true if the supplied handle is an instance of the specified type 00631 */ 00632 template<class D, class T> 00633 bool instanceof(MemberHandle<T>& mh) 00634 { 00635 return NULL != cast<D>(mh, false); 00636 } 00637 00638 /** 00639 * Perform an instanceof check on a MemberHandle. 00640 * 00641 * @param mh the MemberHandle from which to perform the test 00642 * 00643 * @return true if the supplied handle is an instance of the specified type 00644 */ 00645 template<class D, class T> 00646 bool instanceof(const MemberHandle<T>& mh) 00647 { 00648 return NULL != cast<D>(mh, false); 00649 } 00650 00651 COH_CLOSE_NAMESPACE2 00652 00653 #endif // COH_MEMBER_HANDLE_HPP