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

E26041-01

coherence/lang/MemberHandle.hpp

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