coherence/lang/MemberHandle.hpp

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