coherence/lang/MemberHolder.hpp

00001 /*
00002 * MemberHolder.hpp
00003 *
00004 * Copyright (c) 2000, 2009, 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 ? MUTABLE : SAFE_CONST),
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_CONST || !oGuardian._isEscaped())
00244                 {
00245                 // non-escaped, or SAFE_CONST, 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 >= CONST)
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 >= CONST)
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 >= CONST)
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_CONST || !oGuardian._isEscaped())
00435                 {
00436                 // non-escaped, or SAFE_CONST, 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
Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.