Oracle Coherence for C++ API
Release 3.6.0.0
E15728-01

- Main Page
- Namespaces
- Classes
- Files

# coherence/lang/MemberHolder.hpp

    00001 /*
    00002 * MemberHolder.hpp
    00003 *
    00004 * Copyright (c) 2000, 2010, 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 © 2000, 2010, Oracle and/or its affiliates. All rights reserved.