Oracle Coherence for C++ API
Release 3.7.1.0
E22845-01
00001 /* 00002 * MemberHolder.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_HOLDER_HPP 00017 #define COH_MEMBER_HOLDER_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 #include "coherence/lang/TypedHolder.hpp" 00027 00028 #include <ostream> 00029 00030 COH_OPEN_NAMESPACE2(coherence,lang) 00031 00032 00033 /** 00034 * MemberHolder is a thread-safe handle implementation which supports 00035 * referencing Objects as either Handles or Views. MemberHolder can safely be 00036 * used in place of View but adds the ability to attempt a safe down cast to a 00037 * Handle. This differs from the C++ const_cast in that the down cast will only 00038 * succeed if the MemberHolder had been assigned from a Handle, an assignment 00039 * from a View results in a MemberHolder whose down cast operation will throw 00040 * a ClassCastException. 00041 * 00042 * MemberHolder is not for general use, instead it is a convenience handle type 00043 * which can be used for container like classes, which need to be able to 00044 * contain both Handles and Views. 00045 * 00046 * Note: In the rare case that a MemberHolder is declared via the mutable 00047 * keyword, the MemberHolder must be informed of this fact by setting 00048 * fMutable to true during construction. 00049 * 00050 * @author mf 2008.01.09 00051 */ 00052 template<class T> 00053 class MemberHolder 00054 : public SmartMember 00055 { 00056 // ----- typedefs ------------------------------------------------------- 00057 00058 public: 00059 /** 00060 * The type of the values the holder can reference. 00061 */ 00062 typedef const T ValueType; 00063 00064 /** 00065 * The Handle type for the referenced Object. 00066 */ 00067 typedef typename T::Handle ValueHandle; 00068 00069 /** 00070 * The View type for the referenced Object. 00071 */ 00072 typedef typename T::View ValueView; 00073 00074 /** 00075 * The Holder type for the referenced Object. 00076 */ 00077 typedef typename T::Holder ValueHolder; 00078 00079 /** 00080 * Result type for a non-const get operation. 00081 */ 00082 typedef TypedHolder<T> GetType; 00083 00084 00085 // -------- constructors ------------------------------------------------ 00086 00087 public: 00088 /** 00089 * Construct a new MemberHolder referencing NULL via a handle. 00090 * 00091 * @param oGuardian the object that protects this member 00092 */ 00093 MemberHolder(const Object& oGuardian) 00094 : SmartMember(oGuardian), m_fView(false), m_po(NULL) 00095 { 00096 } 00097 00098 /** 00099 * Construct a new MemberHolder referencing the specified Object. 00100 * 00101 * @param oGuardian the object that protects this member 00102 * @param that the Object to reference 00103 */ 00104 MemberHolder(const Object& oGuardian, const TypedHolder<T>& that) 00105 : SmartMember(oGuardian), m_fView(that.m_fView), m_po(NULL) 00106 { 00107 T* po = const_cast<T*>(that.m_cpo); 00108 if (po != NULL) 00109 { 00110 bool fEscaped = oGuardian._isEscaped(); 00111 if (m_fView) 00112 { 00113 ((const T*) po)->_attach(fEscaped); 00114 } 00115 else 00116 { 00117 po->_attach(fEscaped); 00118 } 00119 m_po = po; 00120 } 00121 } 00122 00123 /** 00124 * Construct a new MemberHolder referencing the specified Object. 00125 * 00126 * @param oGuardian the object that protects this member 00127 * @param that the Object to reference 00128 * @param fMutable true if the member is declared as mutable, false 00129 * if declared as const 00130 */ 00131 MemberHolder(const Object& oGuardian, const TypedHolder<T>& that, 00132 bool fMutable) 00133 : SmartMember(oGuardian, fMutable ? forever_mutable : safe_immutable), 00134 m_fView(that.m_fView), m_po(NULL) 00135 { 00136 T* po = const_cast<T*>(that.m_cpo); 00137 if (po != NULL) 00138 { 00139 bool fEscaped = oGuardian._isEscaped(); 00140 if (m_fView) 00141 { 00142 ((const T*) po)->_attach(fEscaped); 00143 } 00144 else 00145 { 00146 po->_attach(fEscaped); 00147 } 00148 m_po = po; 00149 } 00150 } 00151 00152 /** 00153 * Destroy the MemberHolder. 00154 */ 00155 ~MemberHolder() 00156 { 00157 T* po = m_po; 00158 bool fView = m_fView; 00159 00160 if (po != NULL) 00161 { 00162 m_po = NULL; 00163 try 00164 { 00165 bool fEscaped = getGuardian()._isEscaped(); 00166 if (fView) 00167 { 00168 ((const T*) po)->_detach(fEscaped); 00169 } 00170 else 00171 { 00172 po->_detach(fEscaped); 00173 } 00174 } 00175 catch (const std::exception& e) 00176 { 00177 // Exception::View is not a known type within this file 00178 std::cerr << "Error during ~MemberHolder: " << e.what() 00179 << std::endl; 00180 return; // can't re-throw from within destructor 00181 } 00182 } 00183 } 00184 00185 protected: 00186 /** 00187 * Construct a MemberHolder without any associated guardian. 00188 * 00189 * The new MemberHolder is not usable until the guardian is specified. 00190 */ 00191 MemberHolder() 00192 : SmartMember(), m_fView(false), m_po(NULL) 00193 { 00194 } 00195 00196 private: 00197 /** 00198 * Blocked copy constructor. 00199 */ 00200 MemberHolder(const MemberHolder&); 00201 00202 00203 // ----- operators ------------------------------------------------------ 00204 00205 public: 00206 /** 00207 * Assign this MemberHolder to reference the same Object (and in the 00208 * same manner) as the specified MemberHolder. 00209 * 00210 * @param that the object to reference 00211 * 00212 * @return a reference to this MemberHolder 00213 */ 00214 MemberHolder& operator=(const MemberHolder& that) 00215 { 00216 set(that); // assign from snapshot 00217 return *this; 00218 } 00219 00220 /** 00221 * Assign this MemberHolder to reference the same Object (and in the 00222 * same manner) as the specified MemberHolder. 00223 * 00224 * @param that the object to reference 00225 * 00226 * @return a reference to this MemberHolder 00227 */ 00228 MemberHolder& operator=(const TypedHolder<T>& that) 00229 { 00230 set(that); 00231 return *this; 00232 } 00233 00234 /** 00235 * Return a View to the referenced Object. 00236 * 00237 * @return a View to the referenced Object 00238 */ 00239 operator ValueView() const 00240 { 00241 const Object& oGuardian = getGuardian(); 00242 00243 if (m_nMutability == safe_immutable || !oGuardian._isEscaped()) 00244 { 00245 // non-escaped, or safe_immutable, synchronization not required 00246 return ValueView(m_po); 00247 } 00248 else 00249 { 00250 SynchronizedMemberReadBlock::Guard guard(oGuardian); 00251 return ValueView(m_po); // must occur in syncRead scope 00252 } 00253 } 00254 00255 /** 00256 * Return a View to the referenced Object. 00257 * 00258 * @return a View to the referenced Object 00259 */ 00260 template<class PT> 00261 operator TypedHandle<const PT>() const 00262 { 00263 return (ValueView) *this; 00264 } 00265 00266 /** 00267 * Return a TypedHolder to the referenced Object. 00268 * 00269 * @return a TypedHolder to the referenced Object 00270 */ 00271 template<class PT> 00272 operator TypedHolder<PT>() const 00273 { 00274 return get(); 00275 } 00276 00277 /** 00278 * Dereference the MemberHolder. 00279 * 00280 * @return a const pointer to the referenced Object 00281 */ 00282 ValueView operator->() const 00283 { 00284 return (ValueView) *this; 00285 } 00286 00287 /** 00288 * Dereference this handle, returning <tt>T&</tt>. 00289 * 00290 * @return a raw <tt>T&</tt> reference to the referenced Object 00291 * 00292 * @throws NullPointerException if the this handle is @c NULL 00293 */ 00294 const T& operator*() const 00295 { 00296 return *get(); 00297 } 00298 00299 // ----- SmartMember interface ------------------------------------------ 00300 00301 protected: 00302 /** 00303 * {@inheritDoc} 00304 */ 00305 virtual void onEscape(bool fEscaped) const 00306 { 00307 T* po = m_po; 00308 if (po != NULL) 00309 { 00310 if (m_fView) 00311 { 00312 const T* cpo = po; 00313 cpo->_attach(fEscaped); // new attach 00314 cpo->_detach(!fEscaped); // old detach 00315 } 00316 else 00317 { 00318 po->_attach(fEscaped); // new attach 00319 po->_detach(!fEscaped); // old detach 00320 } 00321 } 00322 00323 SmartMember::onEscape(fEscaped); 00324 } 00325 00326 // ----- helper methods ------------------------------------------------- 00327 00328 protected: 00329 /** 00330 * Set the Holder to reference an Object via a View. 00331 * 00332 * @param that the Object to reference 00333 * @param pSync the synch block to delegate to or NULL to create one 00334 */ 00335 void set(const TypedHolder<T>& that, 00336 SynchronizedMemberWriteBlock *pSync = NULL) 00337 { 00338 const Object& oGuardian = getGuardian(); 00339 bool fEscaped = oGuardian._isEscaped(); 00340 T* pNew = const_cast<T*>(that.m_cpo); 00341 bool fNewView = that.m_fView; 00342 T* pOld; 00343 bool fOldView; 00344 00345 if (pNew != NULL) 00346 { 00347 if (fNewView) 00348 { 00349 ((const T*) pNew)->_attach(fEscaped); 00350 } 00351 else 00352 { 00353 pNew->_attach(fEscaped); 00354 } 00355 } 00356 00357 if (pSync != NULL) 00358 { 00359 // sync block 00360 SynchronizedMemberWriteBlock syncWrite(oGuardian, pSync); 00361 if (m_nMutability >= forever_immutable) 00362 { 00363 coh_throw_illegal_state("attempt to set const MemberHolder"); 00364 } 00365 00366 pOld = m_po; 00367 fOldView = m_fView; 00368 00369 m_po = pNew; 00370 m_fView = fNewView; 00371 } 00372 else if (fEscaped) 00373 { 00374 // sync block 00375 SynchronizedMemberWriteBlock::Guard guard(oGuardian); 00376 if (m_nMutability >= forever_immutable) 00377 { 00378 coh_throw_illegal_state("attempt to set const MemberHolder"); 00379 } 00380 pOld = m_po; 00381 fOldView = m_fView; 00382 00383 m_po = pNew; 00384 m_fView = fNewView; 00385 } 00386 else 00387 { 00388 if (m_nMutability >= forever_immutable) 00389 { 00390 coh_throw_illegal_state("attempt to set const MemberHolder"); 00391 } 00392 pOld = m_po; 00393 fOldView = m_fView; 00394 00395 m_po = pNew; 00396 m_fView = fNewView; 00397 } 00398 00399 if (pOld != NULL) 00400 { 00401 if (fOldView) 00402 { 00403 ((const T*) pOld)->_detach(fEscaped); 00404 } 00405 else 00406 { 00407 pOld->_detach(fEscaped); 00408 } 00409 } 00410 } 00411 00412 /** 00413 * Return a TypedHolder referencing the same Object as this 00414 * MemberHolder 00415 * 00416 * @param pSync the sync block to delegate to or NULL to create one 00417 * 00418 * @return a TypedHolder referencing the same Object as this 00419 * MemberHolder 00420 */ 00421 TypedHolder<T> get(SynchronizedMemberReadBlock* pSync = NULL) const 00422 { 00423 const Object& oGuardian = getGuardian(); 00424 00425 if (pSync != NULL) 00426 { 00427 SynchronizedMemberReadBlock syncRead(oGuardian, pSync); 00428 if (m_fView) 00429 { 00430 return ValueView(m_po); // must occur in syncRead scope 00431 } 00432 return ValueHandle(m_po); // must occur in syncRead scope 00433 } 00434 else if (m_nMutability == safe_immutable || !oGuardian._isEscaped()) 00435 { 00436 // non-escaped, or safe_immutable, synchronization not required 00437 if (m_fView) 00438 { 00439 return ValueView(m_po); 00440 } 00441 return ValueHandle(m_po); 00442 } 00443 else 00444 { 00445 SynchronizedMemberReadBlock::Guard guard(oGuardian); 00446 if (m_fView) 00447 { 00448 return ValueView(m_po); // must occur in syncRead scope 00449 } 00450 return ValueHandle(m_po); // must occur in syncRead scope 00451 } 00452 } 00453 00454 00455 // ----- data members --------------------------------------------------- 00456 00457 protected: 00458 /** 00459 * True iff a View is held, i.e. down casting to a Handle is not 00460 * allowed. 00461 */ 00462 bool m_fView; 00463 00464 /** 00465 * The referenced Object. 00466 */ 00467 T* m_po; 00468 00469 00470 // ----- friends -------------------------------------------------------- 00471 00472 /** 00473 * @internal 00474 */ 00475 template<class> friend class Array; 00476 00477 /** 00478 * @internal 00479 */ 00480 friend class SynchronizedMemberReadBlock; 00481 00482 /** 00483 * @internal 00484 */ 00485 friend class SynchronizedMemberWriteBlock; 00486 }; 00487 00488 00489 // ----- non-member operators and functions --------------------------------- 00490 00491 /** 00492 * Output a human-readable description of the given MemberHolder to the 00493 * specified stream. 00494 * 00495 * @param out the stream used to output the description 00496 * @param th the MemberHolder to describe 00497 * 00498 * @return the supplied stream 00499 */ 00500 template<class T> std::ostream& operator<<(std::ostream& out, const MemberHolder<T>& th) 00501 { 00502 out << (typename T::View) th; 00503 return out; 00504 } 00505 00506 /** 00507 * Assign the specified holder to NULL. 00508 * 00509 * @param mh the holder to clear 00510 */ 00511 template<class T> void clear_handle(MemberHolder<T>& mh) 00512 { 00513 mh = NULL; 00514 } 00515 00516 /** 00517 * Return true if the supplied holder equals NULL. 00518 * 00519 * @param mh the holder to test 00520 * 00521 * @return true iff the supplied holder equals NULL 00522 */ 00523 template<class T> 00524 bool is_null(const MemberHolder<T>& mh) 00525 { 00526 return mh == NULL; 00527 } 00528 00529 /** 00530 * Perform a dynamic cast the pointer associated with the MemberHolder 00531 * to a the specified handle/view type. 00532 * 00533 * @param mh the MemberHolder from which to perform the cast 00534 * @param fThrow true if an exception is to be thrown on a failed cast 00535 * 00536 * @return the casted pointer, or NULL if the cast fails and fThrow is false 00537 * 00538 * @throws ClassCastException if the cast fails and fThrow is true 00539 */ 00540 template<class D, class T> 00541 D cast(const MemberHolder<T>& mh, bool fThrow = true) 00542 { 00543 return cast<D>((TypedHolder<T>) mh, fThrow); 00544 } 00545 00546 /** 00547 * Perform an instanceof check on a handle or view. 00548 * 00549 * @param mh the MemberHolder from which to perform the test 00550 * 00551 * @return true if the supplied handle is an instance of the specified type 00552 */ 00553 template<class D, class T> 00554 bool instanceof(const MemberHolder<T>& mh) 00555 { 00556 return instanceof<D>((TypedHolder<T>) mh); 00557 } 00558 00559 COH_CLOSE_NAMESPACE2 00560 00561 #endif // COH_MEMBER_HOLDER_HPP