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

- Main Page
- Namespaces
- Classes
- Files

# coherence/lang/MemberHandle.hpp

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

Copyright © 2000, 2010, Oracle and/or its affiliates. All rights reserved.