Oracle Fusion Middleware C++ API Reference for Oracle Coherence
12c (12.1.2)

E26041-01

coherence/lang/MemberHolder.hpp

00001 /*
00002 * MemberHolder.hpp
00003 *
00004 * Copyright (c) 2000, 2013, 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, public ChainedHandleElement
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), ChainedHandleElement(/*fView*/ false),
00095               m_po(NULL)
00096             {
00097             if (oGuardian._isEscaped())
00098                 {
00099                 m_prev = m_next = NULL;
00100                 }
00101             }
00102 
00103         /**
00104         * Construct a new MemberHolder referencing the specified Object.
00105         *
00106         * @param oGuardian  the object that protects this member
00107         * @param that       the Object to reference
00108         */
00109         MemberHolder(const Object& oGuardian, const TypedHolder<T>& that)
00110             : SmartMember(oGuardian), ChainedHandleElement(/*fView*/ false),
00111               m_po(NULL)
00112             {
00113             if (oGuardian._isEscaped())
00114                 {
00115                 m_prev = m_next = NULL;
00116                 }
00117             set(that);
00118             }
00119 
00120         /**
00121         * Construct a new MemberHolder referencing the specified Object.
00122         *
00123         * @param oGuardian  the object that protects this member
00124         * @param that       the Object to reference
00125         * @param fMutable   true if the member is declared as mutable, false
00126         *                   if declared as const
00127         */
00128         MemberHolder(const Object& oGuardian, const TypedHolder<T>& that,
00129                 bool fMutable)
00130             : SmartMember(oGuardian), ChainedHandleElement(/*fView*/ false),
00131               m_po(NULL)
00132             {
00133             if (oGuardian._isEscaped())
00134                 {
00135                 m_prev = m_next = NULL;
00136                 }
00137             set(that);
00138             m_nMutability = fMutable ? forever_mutable : safe_immutable;
00139             }
00140 
00141         /**
00142         * Destroy the MemberHolder.
00143         */
00144         ~MemberHolder()
00145             {
00146             try
00147                 {
00148                 m_nMutability = inherited;
00149                 set(NULL);
00150                 }
00151             catch (const std::exception& e)
00152                 {
00153                 // Exception::View is not a known type within this file
00154                 std::cerr << "Error during ~MemberHolder: " << e.what() << std::endl;
00155                 return; // can't re-throw from within destructor
00156                 }
00157             }
00158 
00159     protected:
00160         /**
00161         * Construct a MemberHolder without any associated guardian.
00162         *
00163         * The new MemberHolder is not usable until the guardian is specified.
00164         */
00165         MemberHolder()
00166             : SmartMember(), ChainedHandleElement(/*fView*/ false), m_po(NULL)
00167             {
00168             }
00169 
00170     private:
00171         /**
00172         * Blocked copy constructor.
00173         */
00174         MemberHolder(const MemberHolder&);
00175 
00176 
00177     // ----- operators ------------------------------------------------------
00178 
00179     public:
00180         /**
00181         * Assign this MemberHolder to reference the same Object (and in the
00182         * same manner) as the specified MemberHolder.
00183         *
00184         * @param that  the object to reference
00185         *
00186         * @return a reference to this MemberHolder
00187         */
00188         MemberHolder& operator=(const MemberHolder& that)
00189             {
00190             set(that); // assign from snapshot
00191             return *this;
00192             }
00193 
00194         /**
00195         * Assign this MemberHolder to reference the same Object (and in the
00196         * same manner) as the specified MemberHolder.
00197         *
00198         * @param that  the object to reference
00199         *
00200         * @return a reference to this MemberHolder
00201         */
00202         MemberHolder& operator=(const TypedHolder<T>& that)
00203             {
00204             set(that);
00205             return *this;
00206             }
00207 
00208         /**
00209         * Return a View to the referenced Object.
00210         *
00211         * @return a View to the referenced Object
00212         */
00213         operator ValueView() const
00214             {
00215             if (m_prev == NULL)
00216                 {
00217                 if (m_nMutability == safe_immutable)
00218                     {
00219                     // safe_immutable, synchronization not required
00220                     return ValueView(m_po);
00221                     }
00222                 else
00223                     {
00224                     SynchronizedMemberReadBlock::Guard guard(getGuardian());
00225                     return ValueView(m_po); // must occur in syncRead scope
00226                     }
00227                 }
00228             else
00229                 {
00230                 return TypedHandle<const T>(m_po, *this);
00231                 }
00232             }
00233 
00234         /**
00235         * Return a View to the referenced Object.
00236         *
00237         * @return a View to the referenced Object
00238         */
00239         template<class PT>
00240         operator TypedHandle<const PT>() const
00241             {
00242             return (ValueView) *this;
00243             }
00244 
00245         /**
00246         * Return a TypedHolder to the referenced Object.
00247         *
00248         * @return a TypedHolder to the referenced Object
00249         */
00250         template<class PT>
00251         operator TypedHolder<PT>() const
00252             {
00253             return get();
00254             }
00255 
00256         /**
00257         * Dereference the MemberHolder.
00258         *
00259         * @return a const pointer to the referenced Object
00260         */
00261         ValueView operator->() const
00262             {
00263             return (ValueView) *this;
00264             }
00265 
00266         /**
00267         * Dereference this handle, returning <tt>T&</tt>.
00268         *
00269         * @return a raw <tt>T&</tt> reference to the referenced Object
00270         *
00271         * @throws NullPointerException if the this handle is @c NULL
00272         */
00273         const T& operator*() const
00274             {
00275             return *get();
00276             }
00277 
00278     // ----- SmartMember interface ------------------------------------------
00279 
00280     protected:
00281         /**
00282         * {@inheritDoc}
00283         */
00284         virtual void onEscape(bool fEscaped) const
00285             {
00286             T* po = m_po;
00287             if (po)
00288                 {
00289                 if (m_fView)
00290                     {
00291                     ((const T*) po)->_attach(fEscaped);
00292                     }
00293                 else
00294                     {
00295                     po->_attach(fEscaped);
00296                     }
00297                 }
00298 
00299             if (fEscaped)
00300                 {
00301                 performAction(unlink());
00302                 m_prev = m_next = NULL;
00303                 }
00304             else
00305                 {
00306                 if (po)
00307                     {
00308                     if (m_fView)
00309                         {
00310                         ((const T*) po)->_detach(/*fEscaped*/ true);
00311                         }
00312                     else
00313                         {
00314                         po->_detach(/*fEscaped*/ true);
00315                         }
00316                     }
00317                 m_prev = m_next = this;
00318                 }
00319 
00320             SmartMember::onEscape(fEscaped);
00321             }
00322 
00323         /**
00324         * {@inheritDoc}
00325         */
00326         virtual size64_t retained() const
00327             {
00328             TypedHolder<T> oh = get();
00329             return oh == NULL
00330                     ? 0
00331                     : oh->sizeOf(/*fDeep*/ true);
00332             }
00333 
00334     // ----- helper methods -------------------------------------------------
00335 
00336     protected:
00337         /**
00338         * Set the Holder to reference an Object via a View.
00339         *
00340         * @param that   the Object to reference
00341         * @param pSync  the synch block to delegate to or NULL to create one
00342         */
00343         void set(const TypedHolder<T>& that,
00344                 SynchronizedMemberWriteBlock *pSync = NULL)
00345             {
00346             if (m_prev == NULL)
00347                 {
00348                 setEscaped(that, pSync);
00349                 }
00350             else if (m_nMutability >= forever_immutable)
00351                 {
00352                 coh_throw_illegal_state("attempt to set const MemberHolder");
00353                 }
00354             else
00355                 {
00356                 performAction(link(that));
00357                 m_po    = const_cast<T*>(that.m_cpo);
00358                 m_fView = that.m_fView;
00359                 }
00360             }
00361 
00362         /**
00363         * Set the escaped Holder to reference an Object via a View.
00364         *
00365         * @param that   the Object to reference
00366         * @param pSync  the synch block to delegate to or NULL to create one
00367         */
00368         void setEscaped(const TypedHolder<T>& that,
00369                 SynchronizedMemberWriteBlock *pSync = NULL)
00370             {
00371             const Object& oGuardian = getGuardian();
00372             T*    pNew              = const_cast<T*>(that.m_cpo);
00373             bool  fNewView          = that.m_fView;
00374             T*    pOld;
00375             bool  fOldView;
00376 
00377             if (pNew != NULL)
00378                 {
00379                 if (fNewView)
00380                     {
00381                     ((const T*) pNew)->_attach(/*fEscaped*/ true);
00382                     }
00383                 else
00384                     {
00385                     pNew->_attach(/*fEscaped*/ true);
00386                     }
00387                 }
00388 
00389             if (pSync == NULL)
00390                 {
00391                 // sync block
00392                 SynchronizedMemberWriteBlock::Guard guard(oGuardian);
00393                 if (m_nMutability >= forever_immutable)
00394                     {
00395                     coh_throw_illegal_state("attempt to set const MemberHolder");
00396                     }
00397                 pOld     = m_po;
00398                 fOldView = m_fView;
00399 
00400                 m_po    = pNew;
00401                 m_fView = fNewView;
00402                 }
00403             else
00404                 {
00405                 // sync block
00406                 SynchronizedMemberWriteBlock syncWrite(oGuardian, pSync);
00407                 if (m_nMutability >= forever_immutable)
00408                     {
00409                     coh_throw_illegal_state("attempt to set const MemberHolder");
00410                     }
00411 
00412                 pOld     = m_po;
00413                 fOldView = m_fView;
00414 
00415                 m_po    = pNew;
00416                 m_fView = fNewView;
00417                 }
00418 
00419             if (pOld != NULL)
00420                 {
00421                 if (fOldView)
00422                     {
00423                     ((const T*) pOld)->_detach(/*fEscaped*/ true);
00424                     }
00425                 else
00426                     {
00427                     pOld->_detach(/*fEscaped*/ true);
00428                     }
00429                 }
00430             }
00431 
00432         /**
00433          * Return a TypedHolder referencing the same Object as this
00434          * MemberHolder
00435          *
00436          * @param pSync  the sync block to delegate to or NULL to create one
00437          *
00438          * @return a TypedHolder referencing the same Object as this
00439          *         MemberHolder
00440          */
00441         TypedHolder<T> get(SynchronizedMemberReadBlock* pSync = NULL) const
00442             {
00443             if (m_prev == NULL)
00444                 {
00445                 return getEscaped(pSync);
00446                 }
00447             else if (m_fView)
00448                 {
00449                 return TypedHandle<const T>(m_po, *this);
00450                 }
00451             else
00452                 {
00453                 return TypedHandle<T>(m_po, *this);
00454                 }
00455             }
00456 
00457         /**
00458          * Return a TypedHolder referencing the same Object as this
00459          * MemberHolder
00460          *
00461          * @param pSync  the sync block to delegate to or NULL to create one
00462          *
00463          * @return a TypedHolder referencing the same Object as this
00464          *         MemberHolder
00465          */
00466         TypedHolder<T> getEscaped(SynchronizedMemberReadBlock* pSync = NULL) const
00467             {
00468             const Object& oGuardian = getGuardian();
00469 
00470             if (pSync != NULL)
00471                 {
00472                 SynchronizedMemberReadBlock syncRead(oGuardian, pSync);
00473                 if (m_fView)
00474                     {
00475                     return ValueView(m_po); // must occur in syncRead scope
00476                     }
00477                 return ValueHandle(m_po); // must occur in syncRead scope
00478                 }
00479             else if (m_nMutability == safe_immutable)
00480                 {
00481                 // safe_immutable, synchronization not required
00482                 if (m_fView)
00483                     {
00484                     return ValueView(m_po);
00485                     }
00486                 return ValueHandle(m_po);
00487                 }
00488             else
00489                 {
00490                 SynchronizedMemberReadBlock::Guard guard(oGuardian);
00491                 if (m_fView)
00492                     {
00493                     return ValueView(m_po); // must occur in syncRead scope
00494                     }
00495                 return ValueHandle(m_po); // must occur in syncRead scope
00496                 }
00497             }
00498 
00499         /**
00500         * Perform the specified action.
00501         *
00502         * @param nAction  the action to perform
00503         */
00504         void performAction(Action nAction) const
00505             {
00506             T* po = m_po;
00507             switch (nAction)
00508                 {
00509                 case action_error:
00510                     coh_throw_illegal_state("corrupted ChainedHandleElement");
00511                 case action_flip:
00512                     if (NULL != po) ((const T*) po)->_attach(/*fEscaped*/ false);
00513                     // fall through
00514                 case action_detach:
00515                     if (NULL != po)
00516                         {
00517                         if (m_fView)
00518                             {
00519                             ((const T*) po)->_detach(/*fEscaped*/ false);
00520                             }
00521                         else
00522                             {
00523                             po->_detach(/*fEscaped*/ false);
00524                             }
00525                         }
00526                     // fall through
00527                 case action_none:
00528                 default:
00529                     break;
00530                 }
00531             }
00532 
00533 
00534     // ----- data members ---------------------------------------------------
00535 
00536     protected:
00537         /**
00538         * The referenced Object.
00539         */
00540         T* m_po;
00541 
00542 
00543     // ----- friends --------------------------------------------------------
00544 
00545     /**
00546     * @internal
00547     */
00548     template<class> friend class Array;
00549 
00550     /**
00551     * @internal
00552     */
00553     friend class SynchronizedMemberReadBlock;
00554 
00555     /**
00556     * @internal
00557     */
00558     friend class SynchronizedMemberWriteBlock;
00559     };
00560 
00561 
00562 // ----- non-member operators and functions ---------------------------------
00563 
00564 /**
00565 * Output a human-readable description of the given MemberHolder to the
00566 * specified stream.
00567 *
00568 * @param out  the stream used to output the description
00569 * @param th   the MemberHolder to describe
00570 *
00571 * @return the supplied stream
00572 */
00573 template<class T> std::ostream& operator<<(std::ostream& out, const MemberHolder<T>& th)
00574     {
00575     out << (typename T::View) th;
00576     return out;
00577     }
00578 
00579 /**
00580 * Assign the specified holder to NULL.
00581 *
00582 * @param mh the holder to clear
00583 */
00584 template<class T> void clear_handle(MemberHolder<T>& mh)
00585     {
00586     mh = NULL;
00587     }
00588 
00589 /**
00590 * Return true if the supplied holder equals NULL.
00591 *
00592 * @param mh  the holder to test
00593 *
00594 * @return true iff the supplied holder equals NULL
00595 */
00596 template<class T>
00597 bool is_null(const MemberHolder<T>& mh)
00598     {
00599     return mh == NULL;
00600     }
00601 
00602 /**
00603 * Perform a dynamic cast the pointer associated with the MemberHolder
00604 * to a the specified handle/view type.
00605 *
00606 * @param mh      the MemberHolder from which to perform the cast
00607 * @param fThrow  true if an exception is to be thrown on a failed cast
00608 *
00609 * @return the casted pointer, or NULL if the cast fails and fThrow is false
00610 *
00611 * @throws ClassCastException if the cast fails and fThrow is true
00612 */
00613 template<class D, class T>
00614 D cast(const MemberHolder<T>& mh, bool fThrow = true)
00615     {
00616     return cast<D>((TypedHolder<T>) mh, fThrow);
00617     }
00618 
00619 /**
00620 * Perform an instanceof check on a handle or view.
00621 *
00622 * @param mh  the MemberHolder from which to perform the test
00623 *
00624 * @return true if the supplied handle is an instance of the specified type
00625 */
00626 template<class D, class T>
00627 bool instanceof(const MemberHolder<T>& mh)
00628     {
00629     return instanceof<D>((TypedHolder<T>) mh);
00630     }
00631 
00632 COH_CLOSE_NAMESPACE2
00633 
00634 #endif // COH_MEMBER_HOLDER_HPP
Copyright © 2000, 2013, Oracle and/or its affiliates. All rights reserved.