coherence/lang/MemberHolder.hpp

00001 /*
00002 * MemberHolder.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_HOLDER_HPP
00017 #define COH_MEMBER_HOLDER_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 #include "coherence/lang/TypedHolder.hpp"
00027 
00028 #include <ostream>
00029 
00030 COH_OPEN_NAMESPACE2(coherence,lang)
00031 
00032 class Object;
00033 template<class T> class MemberHandle;
00034 template<class T> class MemberView;
00035 
00036 
00037 /**
00038 * MemberHolder is a thread-safe handle implementation which supports
00039 * referencing Objects as either Handles or Views. MemberHolder can safely be
00040 * used in place of View but adds the ability to attempt a safe down cast to a
00041 * Handle. This differs from the C++ const_cast in that the down cast will only
00042 * succeed if the MemberHolder had been assigned from a Handle, an assignment
00043 * from a View results in a MemberHolder whose down cast operation will throw
00044 * a ClassCastException.
00045 *
00046 * MemberHolder is not for general use, instead it is a convience handle type
00047 * which can be used for container like classes, which need to be able to
00048 * contain both Handles and Views.
00049 *
00050 * @author mf  2008.01.09
00051 */
00052 template<class T>
00053 class MemberHolder
00054         : public SmartMember
00055     {
00056     // ----- typedefs -------------------------------------------------------
00057 
00058     public:
00059         /**
00060         * The type of the values the holder can reference.
00061         */
00062         typedef const T ValueType;
00063 
00064         /**
00065         * The Handle type for the referenced Object.
00066         */
00067         typedef typename T::Handle ValueHandle;
00068 
00069         /**
00070         * The View type for the referenced Object.
00071         */
00072         typedef typename T::View ValueView;
00073 
00074         /**
00075         * Result type for a non-const get operation.
00076         */
00077         typedef TypedHolder<T> GetType;
00078 
00079 
00080     // -------- constructors ------------------------------------------------
00081 
00082     public:
00083         /**
00084         * Construct a new MemberHolder referencing NULL via a handle.
00085         */
00086         MemberHolder(Object& oParent)
00087                 : SmartMember(oParent), m_fView(false), m_po(NULL)
00088             {
00089             }
00090 
00091         /**
00092         * Construct a new MemberHolder refrencing specified Object via a
00093         * Handle or View.
00094         *
00095         * As a Handle is used, the MemberHolder can be used with the
00096         * cast() method to retrieve the Handle from the Holder.
00097         *
00098         * @param oParent  the self() on the object this data member is a
00099         *                 member of
00100         * @param th       a Handle or View to the Object to reference
00101         */
00102         template<class DT> MemberHolder(Object& oParent, const TypedHandle<DT>& th)
00103                 : SmartMember(oParent), m_fView(false), m_po(NULL)
00104             {
00105             // use RTTI to identify the template type is a const
00106             if (typeid(DT*) == typeid(const DT*))
00107                 {
00108                 MemberHolder<T>::setView(th);
00109                 }
00110             else
00111                 {
00112                 // if we are here then the type is non-const, the code still
00113                 // must compile even when it is const, though it will never
00114                 // run in that case. We cast-away constness for compilation,
00115                 // and rely on the runtime check to choose the correct path.
00116                 MemberHolder<T>::setHandle((T*) get_pointer(th));
00117                 }
00118             }
00119 
00120         /**
00121         * Construct a new MemberHolder refrencing the same Object (and in
00122         * the same manner) as the specified TypedHolder.
00123         *
00124         * @param oParent  the self() on the object this data member is a
00125         *                 member of
00126         * @param th       the TypedHolder to initialize from
00127         *
00128         */
00129         template<class DT> MemberHolder(Object& oParent, const TypedHolder<DT>& th)
00130                 : SmartMember(oParent), m_fView(false), m_po(NULL)
00131             {
00132             operator=(th);
00133             }
00134 
00135         /**
00136         * Construct a new MemberHolder refrencing the same Object (and in
00137         * the same manner) as the specified MemberHolder.
00138         *
00139         * @param oParent  the self() on the object this data member is a
00140         *                 member of
00141         * @param that     the MemberHolder to initialize from
00142         */
00143         template<class DT> MemberHolder(Object& oParent, const MemberHolder<DT>& that)
00144                 : SmartMember(oParent), m_fView(false), m_po(NULL)
00145             {
00146             operator=(that);
00147             }
00148 
00149         /**
00150         * Destroy the MemberHolder.
00151         */
00152         ~MemberHolder()
00153             {
00154             try
00155                 {
00156                 setHandle(ValueHandle());
00157                 }
00158             catch (const std::exception& e)
00159                 {
00160                 // Exception::View is not a known type within this file
00161                 std::cerr << "Error during ~MemberHolder: " << e.what() << std::endl;
00162                 return; // can't re-throw from within destructor
00163                 }
00164             }
00165 
00166     protected:
00167         /**
00168         * Construct a MemberHolder without any associated parent.
00169         *
00170         * The new MemberHolder is not useable until the parent is specified.
00171         */
00172         MemberHolder()
00173             : SmartMember(), m_fView(false), m_po(NULL)
00174             {
00175             }
00176 
00177     private:
00178         /**
00179         * Blocked copy constructor.
00180         */
00181         MemberHolder(const MemberHolder&);
00182 
00183 
00184     // ----- operators ------------------------------------------------------
00185 
00186     public:
00187         /**
00188         * Assign this MemberHolder to refrence the same Object (and in the
00189         * same manner) as the specified MemberHolder.
00190         *
00191         * @param that  the MemberHolder to assign from
00192         *
00193         * @return a reference to this MemberHolder
00194         */
00195         MemberHolder& operator=(const MemberHolder& that)
00196             {
00197             operator=((TypedHolder<T>) that); // assign from snapshot
00198             return *this;
00199             }
00200 
00201         /**
00202         * Assign this MemberHolder to refrence the same Object (and in the
00203         * same manner) as the specified MemberHolder.
00204         *
00205         * @param mh  the TypedHolder to assign from
00206         *
00207         * @return a reference to this MemberHolder
00208         */
00209         template<class DT> MemberHolder& operator=(const MemberHolder<DT>& mh)
00210             {
00211             operator=((TypedHolder<DT>) mh);
00212             return *this;
00213             }
00214 
00215         /**
00216         * Assign this MemberHolder to refrence the same Object (and in the
00217         * same manner) as the specified MemberHolder.
00218         *
00219         * @param th  the TypedHolder to assign from
00220         *
00221         * @return a reference to this MemberHolder
00222         */
00223         template<class DT> MemberHolder& operator=(const TypedHolder<DT>& th)
00224             {
00225             set(th);
00226             return *this;
00227             }
00228 
00229         /**
00230         * Assign this MemberHolder to refrence the same Object (and in the
00231         * same manner) as the specified MemberHolder.
00232         *
00233         * @param h  the TypedHandle to assign from
00234         *
00235         * @return a reference to this MemberHolder
00236         */
00237         template<class DT> MemberHolder& operator=(const TypedHandle<DT>& h)
00238             {
00239             // use RTTI to identify the template type is a const
00240             if (typeid(DT*) == typeid(const DT*))
00241                 {
00242                 setView(h);
00243                 }
00244             else
00245                 {
00246                 // if we are here then the type is non-const, the code still
00247                 // must compile even when it is const, though it will never
00248                 // run in that case. We cast-away constness for compilation,
00249                 // and rely on the runtime check to choose the correct path.
00250                 setHandle((T*) get_pointer(h));
00251                 }
00252             return *this;
00253             }
00254 
00255         template<class DT>
00256         MemberHolder& operator=(MemberHandle<DT>& mh)
00257             {
00258             return operator=((ValueHandle) mh);
00259             }
00260 
00261         template<class DT>
00262         MemberHolder& operator=(const MemberHandle<DT>& mh)
00263             {
00264             return operator=((ValueView) mh);
00265             }
00266 
00267         template<class DT>
00268         MemberHolder& operator=(const MemberView<DT>& mv)
00269             {
00270             return operator=((ValueView) mv);
00271             }
00272 
00273         /**
00274         * Assign this MemberHolder to refrence the same Object (and in the
00275         * same manner) as the specified pointer.
00276         *
00277         * @param cp  the pointer to assign from
00278         *
00279         * @return a reference to this MemberHolder
00280         */
00281         MemberHolder& operator=(const T* cp)
00282             {
00283             return operator=((ValueView) cp);
00284             }
00285 
00286         /**
00287         * Return a View to the referenced Object.
00288         *
00289         * @return a View to the referenced Object
00290         */
00291         operator ValueView() const
00292             {
00293             SynchronizedMemberReadBlock syncRead(getParent());
00294             return m_po; // view assignment, could throw
00295             }
00296 
00297         /**
00298         * Return a View to the referenced Object.
00299         *
00300         * @return a View to the referenced Object
00301         */
00302         template<class PT>
00303         operator TypedHandle<const PT>() const
00304             {
00305             return (ValueView) *this;
00306             }
00307 
00308         /**
00309         * Return a TypedHolder to the referenced Object.
00310         *
00311         * @return a TypedHolder to the referenced Object
00312         */
00313         template<class PT>
00314         operator TypedHolder<PT>() const
00315             {
00316             return get();
00317             }
00318 
00319         /**
00320         * Derefrence the MemberHolder.
00321         *
00322         * @return a const pointer to the referenced Object
00323         */
00324         ValueView operator->() const
00325             {
00326             return (ValueView) *this;
00327             }
00328 
00329         /**
00330         * Compare the supplied holder to this holder.
00331         *
00332         * @param mh  the holder to compare against
00333         *
00334         * @return true iff the same object is referenced
00335         */
00336         template<class AT>
00337         bool operator==(const MemberHolder<AT>& mh) const
00338             {
00339             typename MemberHolder<AT>::ValueView v = mh;
00340             return operator==(v);
00341             }
00342 
00343         /**
00344         * Compare the supplied holder to this holder.
00345         *
00346         * @param mh  the holder to compare against
00347         *
00348         * @return true iff different objects are referenced
00349         */
00350         template<class AT>
00351         bool operator!=(const MemberHolder<AT>& mh) const
00352             {
00353             return !operator==(mh);
00354             }
00355 
00356         /**
00357         * Compare the supplied holder to this holder.
00358         *
00359         * @param th  the holder to compare against
00360         *
00361         * @return true iff the same object is referenced
00362         */
00363         template<class AT>
00364         bool operator==(const TypedHolder<AT>& th) const
00365             {
00366             return operator==(get_pointer((typename TypedHolder<AT>::ValueView) th));
00367             }
00368 
00369         /**
00370         * Compare the supplied holder to this holder.
00371         *
00372         * @param th  the holder to compare against
00373         *
00374         * @return true iff different objects are referenced
00375         */
00376         template<class AT>
00377         bool operator!=(const TypedHolder<AT>& th) const
00378             {
00379             return !operator==(th);
00380             }
00381 
00382         /**
00383         * Compare the supplied handle to this holder.
00384         *
00385         * @param h  the handle to compare against
00386         *
00387         * @return true iff the same object is referenced
00388         */
00389         template<class AT>
00390         bool operator==(const TypedHandle<AT>& h) const
00391             {
00392             return operator==(get_pointer(h));
00393             }
00394 
00395         /**
00396         * Compare the supplied handle to this holder.
00397         *
00398         * @param h  the handle to compare against
00399         *
00400         * @return true iff the different objects are referenced
00401         */
00402         template<class AT>
00403         bool operator!=(const TypedHandle<AT>& h) const
00404             {
00405             return !operator==(h);
00406             }
00407 
00408         /**
00409         * Compare the supplied pointer to this holder.
00410         *
00411         * @param cpThat  the pointer to compare against
00412         *
00413         * @return true iff the same object is referenced
00414         */
00415         bool operator==(const Object* cpThat) const
00416             {
00417             SynchronizedMemberReadBlock syncRead(getParent());
00418             return ((const Object*) m_po) == cpThat;
00419             }
00420 
00421         /**
00422         * Compare the supplied pointer to this holder.
00423         *
00424         * @param cpThat  the pointer to compare against
00425         *
00426         * @return true iff different objects are referenced
00427         */
00428         bool operator!=(const Object* cpThat) const
00429             {
00430             return !operator==(cpThat);
00431             }
00432 
00433 
00434     // ----- helper methods -------------------------------------------------
00435 
00436     protected:
00437         /**
00438         * Set the Holder to reference an Object via a View.
00439         *
00440         * @param v      the View to the Object to reference
00441         * @param pSync  the synch block to delegate to or NULL to create one
00442         */
00443         void setView(const TypedHandle<const T>& v, SynchronizedMemberWriteBlock *pSync = NULL)
00444             {
00445             const T* cpNew    = get_pointer(v);
00446             const T* cpAttach = (NULL == cpNew || NULL == cpNew->_attach() ? NULL : cpNew);
00447             const T* cpDetach = NULL;
00448             T*       pDetach  = NULL;
00449 
00450             // sync block
00451                 {
00452                 SynchronizedMemberWriteBlock syncWrite(getParent(), pSync);
00453                 if (m_fView)
00454                     {
00455                     cpDetach = m_po;
00456                     }
00457                 else
00458                     {
00459                     pDetach = m_po;
00460                     }
00461 
00462                 m_po    = const_cast<T*>(cpAttach);
00463                 m_fView = cpAttach != NULL;
00464                 }
00465 
00466             if (pDetach)
00467                 {
00468                 pDetach->_detach();
00469                 }
00470             else if (cpDetach)
00471                 {
00472                 cpDetach->_detach();
00473                 }
00474             }
00475 
00476         /**
00477         * Set the Holder to reference an Object via a Handle.
00478         *
00479         * @param h      the Handle to the Object to reference
00480         * @param pSync  the sync block to delegate to or NULL to create one
00481         */
00482         void setHandle(const TypedHandle<T>& h, SynchronizedMemberWriteBlock *pSync = NULL)
00483             {
00484             T*       pNew     = get_pointer(h);
00485             T*       pAttach  = (NULL == pNew || NULL == pNew->_attach() ? NULL : pNew);
00486             T*       pDetach  = NULL;
00487             const T* cpDetach = NULL;
00488 
00489             // sync block
00490                 {
00491                 SynchronizedMemberWriteBlock syncWrite(getParent(), pSync);
00492                 if (m_fView)
00493                     {
00494                     cpDetach = m_po;
00495                     }
00496                 else
00497                     {
00498                     pDetach = m_po;
00499                     }
00500 
00501                 m_po    = pAttach;
00502                 m_fView = false;
00503                 }
00504 
00505             if (pDetach)
00506                 {
00507                 pDetach->_detach();
00508                 }
00509             else if (cpDetach)
00510                 {
00511                 cpDetach->_detach();
00512                 }
00513             }
00514 
00515         /**
00516         * Set the MemberHolder to reference the same Object as the specified
00517         * TypedHolder.
00518         *
00519         * @param th     the TypedHolder to copy
00520         * @param pSync  the sync block to delegate to or NULL to create one
00521         */
00522         template<class DT> void set(const TypedHolder<DT>& th, SynchronizedMemberWriteBlock *pSync = NULL)
00523             {
00524             ValueHandle hThat = cast<typename DT::Handle>(th, false);
00525             if (NULL == hThat)
00526                 {
00527                 setView(th, pSync);
00528                 }
00529             else
00530                 {
00531                 setHandle(hThat, pSync);
00532                 }
00533             }
00534 
00535         /**
00536          * Return a TypedHolder referencing the same Object as this
00537          * MemberHolder
00538          *
00539          * @param pSync  the sync block to delegate to or NULL to create one
00540          *
00541          * @return a TypedHolder referecning the same Object as this
00542          *         MemberHolder
00543          */
00544         TypedHolder<T> get(SynchronizedMemberReadBlock* pSync = NULL) const
00545             {
00546             SynchronizedMemberReadBlock syncRead(getParent(), pSync);
00547             if (m_fView)
00548                 {
00549                 return (ValueView) m_po;
00550                 }
00551             return (ValueHandle) m_po;
00552             }
00553 
00554 
00555     // ----- data members ---------------------------------------------------
00556 
00557     private:
00558         /**
00559         * True iff a View is held, i.e. down casting to a Handle is not
00560         * allowed.
00561         */
00562         bool m_fView;
00563 
00564         /**
00565         * The referenced Object.
00566         */
00567         T* m_po;
00568 
00569 
00570     // ----- friends --------------------------------------------------------
00571 
00572     /**
00573     * @internal
00574     */
00575     template<class> friend class Array;
00576 
00577     /**
00578     * @internal
00579     */
00580     friend class SynchronizedMemberReadBlock;
00581 
00582     /**
00583     * @internal
00584     */
00585     friend class SynchronizedMemberWriteBlock;
00586     };
00587 
00588 
00589 // ----- non-member operators and functions ---------------------------------
00590 
00591 /**
00592 * Output a human-readable description of the given MemberHolder to the
00593 * specified stream.
00594 *
00595 * @param out  the stream used to output the description
00596 * @param th   the MemberHolder to describe
00597 *
00598 * @return the supplied stream
00599 */
00600 template<class T> std::ostream& operator<<(std::ostream& out, const MemberHolder<T>& th)
00601     {
00602     out << (typename T::View) th;
00603     return out;
00604     }
00605 
00606 /**
00607 * Assign the specified holder to NULL.
00608 *
00609 * @param mh the holder to clear
00610 */
00611 template<class T> void clear_handle(MemberHolder<T>& mh)
00612     {
00613     static TypedHandle<T> hNull;
00614     mh = hNull;
00615     }
00616 
00617 /**
00618 * Return true if the supplied holder equals NULL.
00619 *
00620 * @param mh  the holder to test
00621 *
00622 * @return true iff the supplied holder equals NULL
00623 */
00624 template<class T>
00625 bool is_null(const MemberHolder<T>& mh)
00626     {
00627     return NULL == mh;
00628     }
00629 
00630 /**
00631 * Perform a dynamic cast the pointer associated with the MemberHolder
00632 * to a the specified handle/view type.
00633 *
00634 * @param mh      the MemberHolder from which to perform the cast
00635 * @param fThrow  true if an exception is to be thrown on a failed cast
00636 *
00637 * @return the casted pointer, or NULL if the cast fails and fThrow is false
00638 *
00639 * @throws ClassCastException if the cast fails and fThrow is true
00640 */
00641 template<class D, class T>
00642 D cast(const MemberHolder<T>& mh, bool fThrow = true)
00643     {
00644     return cast<D>((TypedHolder<T>) mh, fThrow);
00645     }
00646 
00647 /**
00648 * Perform an instanceof check on a handle or view.
00649 *
00650 * @param th  the MemberHolder from which to perform the test
00651 *
00652 * @return true if the supplied handle is an instance of the specified type
00653 */
00654 template<class D, class T>
00655 bool instanceof(const MemberHolder<T>& mh)
00656     {
00657     return instanceof<D>((TypedHolder<T>) mh);
00658     }
00659 
00660 /**
00661 * Compare a handle to a holder.
00662 *
00663 * @param h   handle to compare
00664 * @param mh  holder to compare
00665 *
00666 * @return true if both reference the same Object
00667 */
00668 template<class AT, class T>
00669 bool operator==(const TypedHandle<AT>& h, const MemberHolder<T>& mh)
00670     {
00671     return mh == h;
00672     }
00673 
00674 /**
00675 * Compare a Object pointer to a holder.
00676 *
00677 * @param cpo  handle to compare
00678 * @param mh   holder to compare
00679 *
00680 * @return true if both reference the same Object
00681 */
00682 template<class T>
00683 bool operator==(const Object* cpo, const MemberHolder<T>& mh)
00684     {
00685     return mh == cpo;
00686     }
00687 
00688 /**
00689 * Compare a handle to a holder.
00690 *
00691 * @param h   handle to compare
00692 * @param mh  holder to compare
00693 *
00694 * @return true if each references a different Object
00695 */
00696 template<class AT, class T>
00697 bool operator!=(const TypedHandle<AT>& h, const MemberHolder<T>& mh)
00698     {
00699     return mh != h;
00700     }
00701 
00702 /**
00703 * Compare a Object pointer to a holder.
00704 *
00705 * @param cpo  handle to compare
00706 * @param mh   holder to compare
00707 *
00708 * @return true if each references a different Object
00709 */
00710 template<class T>
00711 bool operator!=(const Object* cpo, const MemberHolder<T>& mh)
00712     {
00713     return mh != cpo;
00714     }
00715 
00716 COH_CLOSE_NAMESPACE2
00717 
00718 #endif // COH_MEMBER_HOLDER_HPP
Copyright (c) 2000-2008 Oracle. All rights reserved.