coherence/lang/MemberHandle.hpp

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