Oracle® Fusion Middleware C++ API Reference for Oracle Coherence
14c (14.1.1.0.0)

F23533-01

coherence/lang/MemberHandle.hpp

00001 /*
00002 * MemberHandle.hpp
00003 *
00004 * Copyright (c) 2000, 2020, 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 
00029 COH_OPEN_NAMESPACE2(coherence,lang)
00030 
00031 template<class> class MemberView;
00032 
00033 
00034 /**
00035 * MemberHandle is a thread-safe handle used by an Object to reference its
00036 * non-const child Objects.
00037 *
00038 * MemberHandles transfer the constness of their guardian Object. When a
00039 * MemberHandle is accessed from within a const method of the enclosing
00040 * "parent" class, it will only provide const access to the Object which it
00041 * references. If the enclosing Object becomes only accessed via views the
00042 * MemberHandle will also automatically, and permanently switch its reference
00043 * type from a handle to a view.
00044 *
00045 * Note: In the rare case that a MemberHandle is declared via the mutable
00046 *       keyword, the MemberHandle must be informed of this fact by setting
00047 *       fMutable to true during construction.
00048 *
00049 * @author mf  2007.07.05
00050 *
00051 * @see MemberView
00052 * @see MemberHolder
00053 */
00054 template<class T>
00055 class MemberHandle
00056     : public SmartMember, public ChainedHandleElement
00057     {
00058     // ----- typedefs -------------------------------------------------------
00059 
00060     public:
00061         /**
00062         * The type of the values the handle can reference.
00063         */
00064         typedef T ValueType;
00065 
00066         /**
00067         * The Handle type for the referenced Object.
00068         */
00069         typedef typename T::Handle ValueHandle;
00070 
00071         /**
00072         * The View type for thekil referenced Object.
00073         */
00074         typedef typename T::View ValueView;
00075 
00076         /**
00077         * Result type for a non-const get operation.
00078         */
00079         typedef ValueHandle GetType;
00080 
00081         /**
00082         * Result type for a non-const get operation.
00083         */
00084         typedef ValueView ConstGetType;
00085 
00086 
00087     // -------- constructors ------------------------------------------------
00088 
00089     public:
00090         /**
00091         * Construct a new MemberHandle referencing NULL via a handle.
00092         *
00093         * @param oGuardian  the object that protects this member
00094         */
00095         MemberHandle(const Object& oGuardian)
00096             : SmartMember(oGuardian), ChainedHandleElement(/*fView*/ false),
00097               m_po(NULL)
00098             {
00099             if (oGuardian._isEscaped())
00100                 {
00101                 m_prev = m_next = NULL;
00102                 }
00103             }
00104 
00105         /**
00106         * Construct a new MemberHandle referencing the specified Object via
00107         * a handle.
00108         *
00109         * @param oGuardian   the object that protects this member
00110         * @param that        the Object to reference
00111         */
00112         MemberHandle(const Object& oGuardian, const ValueHandle& that)
00113             : SmartMember(oGuardian), ChainedHandleElement(/*fView*/ false),
00114               m_po(NULL)
00115             {
00116             if (oGuardian._isEscaped())
00117                 {
00118                 m_prev = m_next = NULL;
00119                 }
00120             set(that);
00121             }
00122 
00123         /**
00124         * Construct a new MemberHandle referencing the specified Object via
00125         * a handle.
00126         *
00127         * @param oGuardian  the object that protects this member
00128         * @param that       the Object to reference
00129         * @param fMutable   true if the member is declared as mutable, false
00130         *                   if declared as const
00131         */
00132         MemberHandle(const Object& oGuardian, const ValueHandle& that,
00133                 bool fMutable)
00134             : SmartMember(oGuardian), ChainedHandleElement(/*fView*/ false),
00135               m_po(NULL)
00136             {
00137             if (oGuardian._isEscaped())
00138                 {
00139                 m_prev = m_next = NULL;
00140                 }
00141             set(that);
00142             m_nMutability = fMutable ? forever_mutable : safe_immutable;
00143             }
00144 
00145         /**
00146         * Destroy the MemberHandle.
00147         */
00148         ~MemberHandle()
00149             {
00150             try
00151                 {
00152                 const T* cpo = m_po;
00153                 if (cpo && m_fView && m_prev == NULL)
00154                     {
00155                     // escaped and const (view based ref); set() does not
00156                     // handle this case as it can only occur during destruction
00157                     cpo->_detach(/*fEscaped*/ true);
00158                     }
00159                 else
00160                     {
00161                     // even if cpo == NULL we still may need to call unlink()
00162                     m_nMutability = inherited;
00163                     set(NULL);
00164                     }
00165                 }
00166             catch (const std::exception& e)
00167                 {
00168                 // Exception::View is not a known type within this file
00169                 std::cerr << "Error during ~MemberHandle: " << e.what() << std::endl;
00170                 return; // can't re-throw from within destructor
00171                 }
00172             }
00173 
00174     private:
00175         /**
00176         * Blocked copy constructor.
00177         */
00178         MemberHandle(const MemberHandle&);
00179 
00180 
00181     // ----- operators ------------------------------------------------------
00182 
00183     public:
00184         /**
00185         * Assign the MemberHandle to reference another object.
00186         *
00187         * @param that  the object to reference
00188         *
00189         * @return a reference to this MemberHandle
00190         */
00191         MemberHandle& operator=(const ValueHandle& that)
00192             {
00193             set(that);
00194             return *this;
00195             }
00196 
00197         /**
00198         * Assign this MemberHandle to reference the same Object as the
00199         * specified MemberHandle.
00200         *
00201         * @param that  the object to reference
00202         *
00203         * @return a reference to this MemberHandle
00204         */
00205         MemberHandle& operator=(MemberHandle& that)
00206             {
00207             operator=((ValueHandle) that); // assign from snapshot
00208             return *this;
00209             }
00210 
00211         /**
00212         * Return a View to the referenced Object.
00213         *
00214         * @return a View to the referenced Object
00215         */
00216         operator ValueView() const
00217             {
00218             return get();
00219             }
00220 
00221         /**
00222         * Return a Handle to the referenced Object.
00223         *
00224         * @return a Handle to the referenced Object
00225         */
00226         operator ValueHandle()
00227             {
00228             return get();
00229             }
00230 
00231         /**
00232         * Return a View to the referenced Object.
00233         *
00234         * @return a View to the referenced Object
00235         */
00236         template<class PT>
00237         operator TypedHandle<const PT>() const
00238             {
00239             return get();
00240             }
00241 
00242         /**
00243         * Return a Handle to the referenced Object.
00244         *
00245         * @return a Handle to the referenced Object
00246         */
00247         template<class PT>
00248         operator TypedHandle<PT>()
00249             {
00250             return get();
00251             }
00252 
00253         /**
00254         * Return a TypedHolder to the referenced Object.
00255         *
00256         * @return a TypedHolder to the referenced Object
00257         *
00258         */
00259         template<class PT>
00260         operator TypedHolder<PT>() const
00261             {
00262             return get();
00263             }
00264 
00265         /**
00266         * Return a TypedHolder to the referenced Object.
00267         *
00268         * @return a TypedHolder to the referenced Object
00269         */
00270         template<class PT>
00271         operator TypedHolder<PT>()
00272             {
00273             return get();
00274             }
00275 
00276         /**
00277         * Dereference the MemberHandle.
00278         *
00279         * @return a const pointer to the referenced Object
00280         */
00281         ValueView operator->() const
00282             {
00283             return get();
00284             }
00285 
00286         /**
00287         * Dereference the MemberHandle.
00288         *
00289         * @return a const pointer to the referenced Object
00290         */
00291         ValueHandle operator->()
00292             {
00293             return get();
00294             }
00295 
00296         /**
00297         * Dereference this handle, returning <tt>T&</tt>.
00298         *
00299         * @return a raw <tt>T&</tt> reference to the referenced Object
00300         *
00301         * @throws NullPointerException if the this handle is @c NULL
00302         */
00303         const T& operator*() const
00304             {
00305             return *get();
00306             }
00307 
00308         /**
00309         * Dereference this handle, returning <tt>T&</tt>.
00310         *
00311         * @return a raw <tt>T&</tt> reference to the referenced Object
00312         *
00313         * @throws NullPointerException if the this handle is @c NULL
00314         */
00315         T& operator*()
00316             {
00317             return *get();
00318             }
00319 
00320     private:
00321         /**
00322         * Blocked assignment operator.
00323         */
00324         MemberHandle<T>& operator=(const MemberHandle<T>&);
00325 
00326 
00327     // ----- helper methods -------------------------------------------------
00328 
00329     protected:
00330         /**
00331         * Set the MemberHandle to reference the same Object as the supplied
00332         * Handle.
00333         *
00334         * @param that   the handle to copy
00335         * @param pSync  optional external SyncornizedMemberBlock to use
00336         *               to avoid internal synchronization.
00337         */
00338         void set(const TypedHandle<T>& that,
00339                 SynchronizedMemberWriteBlock* pSync = NULL)
00340             {
00341             if (m_prev == NULL)
00342                 {
00343                 setEscaped(that, pSync);
00344                 }
00345             else if (m_nMutability >= forever_immutable)
00346                 {
00347                 coh_throw_illegal_state("attempt to set const MemberHandle");
00348                 }
00349             else
00350                 {
00351                 performAction(link(that));
00352                 m_po = get_pointer(that);
00353                 }
00354             }
00355 
00356         /**
00357         * Set the MemberHandle to reference the same Object as the supplied
00358         * Handle.
00359         *
00360         * @param that   the handle to copy
00361         * @param pSync  optional external SyncornizedMemberBlock to use
00362         *               to avoid internal synchronization.
00363         */
00364         void setEscaped(const TypedHandle<T>& that,
00365                 SynchronizedMemberWriteBlock* pSync = NULL)
00366             {
00367             const Object& oGuardian = getGuardian();
00368             T*            po        = get_pointer(that);
00369             T*            pDetach   = NULL;
00370             Object*       pAttach   = po == NULL ? NULL : po->_attach(/*fEscaped*/ true);
00371 
00372             if (pSync == NULL)
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 MemberHandle");
00379                     }
00380                 pDetach = m_po;
00381                 m_po    = NULL == pAttach ? NULL : po;
00382                 }
00383             else
00384                 {
00385                 // sync block
00386                 SynchronizedMemberWriteBlock syncWrite(oGuardian, pSync);
00387                 if (m_nMutability >= forever_immutable)
00388                     {
00389                     coh_throw_illegal_state("attempt to set const MemberHandle");
00390                     }
00391                 pDetach = m_po;
00392                 m_po    = NULL == pAttach ? NULL : po;
00393                 }
00394 
00395             if (pDetach)
00396                 {
00397             pDetach->_detach(/*fEscaped*/ true);
00398                 }
00399             }
00400 
00401         /**
00402         * Return a View to the referenced Object.
00403         *
00404         * @param pSync  optional external SyncornizedMemberReadBlock to use
00405         *               to avoid internal synchronization.
00406         *
00407         * @return a View to the referenced Object
00408         */
00409         ValueView get(SynchronizedMemberReadBlock* pSync = NULL) const
00410             {
00411             if (m_prev == NULL)
00412                 {
00413                 return getEscaped(pSync);
00414                 }
00415             else
00416                 {
00417                 return TypedHandle<const T>(m_po, *this);
00418                 }
00419             }
00420 
00421         /**
00422         * Return a View to the referenced Object.
00423         *
00424         * @param pSync  optional external SyncornizedMemberReadBlock to use
00425         *               to avoid internal synchronization.
00426         *
00427         * @return a View to the referenced Object
00428         */
00429         ValueView getEscaped(SynchronizedMemberReadBlock* pSync = NULL) const
00430             {
00431             if (pSync != NULL)
00432                 {
00433                 SynchronizedMemberReadBlock syncRead(getGuardian(), pSync);
00434                 // return of escaped must occur within scope of syncRead
00435                 return ValueView((const T*) m_po);
00436                 }
00437             else if (m_nMutability == safe_immutable)
00438                 {
00439                 // safe_immutable, synchronization not required; also implies view
00440                 return ValueView((const T*) m_po);
00441                 }
00442             else
00443                 {
00444                 SynchronizedMemberReadBlock::Guard guard(getGuardian());
00445                 // return of escaped must occur within scope of guard
00446                 return ValueView((const T*) m_po);
00447                 }
00448             }
00449 
00450         /**
00451         * Return a Handle to the referenced Object.
00452         *
00453         * @param pSync  optional external SyncornizedMemberReadBlock to use
00454         *               to avoid internal synchronization.
00455         *
00456         * @return a Handle to the referenced Object
00457         */
00458         ValueHandle get(SynchronizedMemberReadBlock* pSync = NULL)
00459             {
00460             if (m_prev == NULL)
00461                 {
00462                 return getEscaped(pSync);
00463                 }
00464             else
00465               {
00466                 return TypedHandle<T>(m_po, *this);
00467               }
00468             }
00469 
00470         /**
00471         * Return a Handle to the referenced Object.
00472         *
00473         * @param pSync  optional external SyncornizedMemberReadBlock to use
00474         *               to avoid internal synchronization.
00475         *
00476         * @return a Handle to the referenced Object
00477         */
00478         ValueHandle getEscaped(SynchronizedMemberReadBlock* pSync = NULL)
00479             {
00480             const Object& oGuardian = getGuardian();
00481             if (pSync == NULL)
00482                 {
00483                 SynchronizedMemberReadBlock::Guard guard(oGuardian);
00484                 if (m_fView)
00485                     {
00486                     coh_throw_illegal_state(
00487                         "attempt to access handle from const MemberHandle");
00488                     }
00489                 return ValueHandle(m_po); // must occur within scope of syncRead
00490                 }
00491             else
00492                 {
00493                 SynchronizedMemberReadBlock syncRead(oGuardian, pSync);
00494                 if (m_fView)
00495                     {
00496                     coh_throw_illegal_state(
00497                         "attempt to access handle from const MemberHandle");
00498                     }
00499                 return ValueHandle(m_po); // must occur within scope of syncRead
00500                 }
00501             }
00502 
00503         /**
00504         * Perform the specified action.
00505         *
00506         * @param nAction  the action to perform
00507         */
00508         void performAction(Action nAction) const
00509             {
00510             T* po = m_po;
00511             switch (nAction)
00512                 {
00513                 case action_error:
00514                     coh_throw_illegal_state("corrupted ChainedHandleElement");
00515                 case action_flip:
00516                     if (NULL != po) ((const T*) po)->_attach(/*fEscaped*/ false);
00517                     // fall through
00518                 case action_detach:
00519                     if (NULL != po)
00520                         {
00521                         if (m_fView)
00522                             {
00523                             ((const T*) po)->_detach(/*fEscaped*/ false);
00524                             }
00525                         else
00526                             {
00527                             po->_detach(/*fEscaped*/ false);
00528                             }
00529                         }
00530                     // fall through
00531                 case action_none:
00532                 default:
00533                     break;
00534                 }
00535             }
00536 
00537     // ----- SmartMember interface ------------------------------------------
00538 
00539     protected:
00540         /**
00541         * {@inheritDoc}
00542         *
00543         * The MemberHandle is automatically flipped when the guardian Object
00544         * becomes only referenced via consts.
00545         */
00546         virtual void onConst()
00547             {
00548             bool fEscaped  = m_prev == NULL;
00549             T*   po        = NULL;
00550 
00551             if (fEscaped)
00552                 {
00553                 SynchronizedMemberWriteBlock::Guard guard(getGuardian());
00554                 po = m_po;
00555                 }
00556             else
00557                 {
00558                 po = m_po;
00559                 }
00560 
00561             if (NULL != po)
00562                 {
00563                 // re-attach as const, then detach the old reference
00564                 if (fEscaped)
00565                     {
00566                     ((const T*) po)->_attach(/*fEscaped*/ true);
00567                     po->_detach(/*fEscaped*/ true);
00568                     }
00569                 else if (scan())
00570                     {
00571                     performAction(action_flip);
00572                     }
00573                 }
00574 
00575             m_fView = true;
00576             SmartMember::onConst();
00577             }
00578 
00579         /**
00580         * {@inheritDoc}
00581         */
00582         virtual void onEscape(bool fEscaped) const
00583             {
00584             T* po = m_po;
00585             if (po != NULL)
00586                 {
00587                 if (m_fView)
00588                     {
00589                     const T* cpo = po;
00590                     cpo->_attach(fEscaped);  // new attach
00591                     }
00592                 else
00593                     {
00594                     po->_attach(fEscaped);  // new attach
00595                     }
00596                 }
00597 
00598             if (fEscaped)
00599                 {
00600                 performAction(unlink());
00601                 m_prev = m_next = NULL;
00602                 }
00603             else
00604                 {
00605                 if (po)
00606                     {
00607                     if (m_fView)
00608                         {
00609                         const T* cpo = po;
00610                         cpo->_detach(/*fEscaped*/ true); // old detach
00611                         }
00612                     else
00613                         {
00614                         po->_detach(/*fEscaped*/ true); // old detach
00615                         }
00616                     }
00617                 m_prev = m_next = this;
00618                 }
00619 
00620             SmartMember::onEscape(fEscaped);
00621             }
00622 
00623         /**
00624         * {@inheritDoc}
00625         */
00626         virtual size64_t retained() const
00627             {
00628             ValueView v = get();
00629             return v == NULL
00630                     ? 0
00631                     : v->sizeOf(/*fDeep*/ true);
00632             }
00633 
00634     // ----- data members ---------------------------------------------------
00635 
00636     protected:
00637        /**
00638         * The referenced Object.
00639         */
00640         T* m_po;
00641 
00642 
00643     // ----- friends --------------------------------------------------------
00644 
00645     /**
00646     * @internal
00647     */
00648     template<class D, class H> friend D cast(MemberHandle<T>& mh, bool fThrow);
00649 
00650     /**
00651     * @internal
00652     */
00653     friend class SynchronizedMemberReadBlock;
00654 
00655     /**
00656     * @internal
00657     */
00658     friend class SynchronizedMemberWriteBlock;
00659     };
00660 
00661 
00662 // ----- non-member operators and functions ---------------------------------
00663 
00664 /**
00665 * Output a human-readable description of the given MemberHandle to the
00666 * specified stream.
00667 *
00668 * @param out  the stream used to output the description
00669 * @param mh   the MemberHandle to describe
00670 *
00671 * @return the supplied stream
00672 */
00673 template <typename Char, typename Traits, class T>
00674 COH_INLINE std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& out, const MemberHandle<T>& mh)
00675     {
00676     out << (typename T::View) mh;
00677     return out;
00678     }
00679 
00680 /**
00681 * Assign the specified handle to NULL.
00682 *
00683 * @param mh the handle to clear
00684 */
00685 template<class T> void clear_handle(MemberHandle<T>& mh)
00686     {
00687     mh = NULL;
00688     }
00689 
00690 /**
00691 * Return true if the supplied handle equals NULL.
00692 *
00693 * @param mh  the member handle to test
00694 *
00695 * @return true iff the supplied handle equals NULL
00696 */
00697 template<class T>
00698 bool is_null(const MemberHandle<T>& mh)
00699     {
00700     return mh == NULL;
00701     }
00702 
00703 /**
00704 * Perform a dynamic cast the pointer associated with the MemberHandle
00705 * to a the specified handle/view type.
00706 *
00707 * @param mh      the MemberHandle from which to perform the cast
00708 * @param fThrow  true if an exception is to be thrown on a failed cast
00709 *
00710 * @return the casted pointer, or NULL if the cast fails and fThrow is false
00711 *
00712 * @throws ClassCastException if the cast fails and fThrow is true
00713 */
00714 template<class D, class T>
00715 D cast(MemberHandle<T>& mh, bool fThrow = true)
00716     {
00717     return cast<D>((typename MemberHandle<T>::ValueHandle) mh, fThrow);
00718     }
00719 
00720 /**
00721 * Perform a dynamic cast the pointer associated with the MemberHandle
00722 * to a the specified handle/view type.
00723 *
00724 * @param mh      the MemberHandle from which to perform the cast
00725 * @param fThrow  true if an exception is to be thrown on a failed cast
00726 *
00727 * @return the casted pointer, or NULL if the cast fails and fThrow is false
00728 *
00729 * @throws ClassCastException if the cast fails and fThrow is true
00730 */
00731 template<class D, class T>
00732 D cast(const MemberHandle<T>& mh, bool fThrow = true)
00733     {
00734     return cast<D>((typename MemberHandle<T>::ValueView) mh, fThrow);
00735     }
00736 
00737 /**
00738 * Perform an instanceof check on a MemberHandle.
00739 *
00740 * @param mh  the MemberHandle from which to perform the test
00741 *
00742 * @return true if the supplied handle is an instance of the specified type
00743 */
00744 template<class D, class T>
00745 bool instanceof(MemberHandle<T>& mh)
00746     {
00747     return NULL != cast<D>(mh, false);
00748     }
00749 
00750 /**
00751 * Perform an instanceof check on a MemberHandle.
00752 *
00753 * @param mh  the MemberHandle from which to perform the test
00754 *
00755 * @return true if the supplied handle is an instance of the specified type
00756 */
00757 template<class D, class T>
00758 bool instanceof(const MemberHandle<T>& mh)
00759     {
00760     return NULL != cast<D>(mh, false);
00761     }
00762 
00763 COH_CLOSE_NAMESPACE2
00764 
00765 #endif // COH_MEMBER_HANDLE_HPP
Copyright © 2000, 2020, Oracle and/or its affiliates. All rights reserved.