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

E80355-01

coherence/lang/TypedHolder.hpp

00001 /*
00002 * TypedHolder.hpp
00003 *
00004 * Copyright (c) 2000, 2017, 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_TYPED_HOLDER_HPP
00017 #define COH_TYPED_HOLDER_HPP
00018 
00019 #include "coherence/lang/compatibility.hpp"
00020 
00021 #include "coherence/lang/ChainedHandleElement.hpp"
00022 #include "coherence/lang/TypedHandle.hpp"
00023 
00024 #include <ostream>
00025 
00026 COH_OPEN_NAMESPACE2(coherence,lang)
00027 
00028 class Object;
00029 template<class T> class MemberHolder;
00030 
00031 /**
00032 * A handle implementation which supports referencing Objects as either
00033 * Handles or Views. TypedHolder can safely be used in place of View
00034 * but adds the ability to attempt a safe down cast to a Handle. This differs
00035 * from a const_cast in that the down cast will only succeed if the
00036 * TypedHolder had been assigned from a Handle, an assignment from a View
00037 * results in a TypedHolder whose down cast operation will fail with a
00038 * ClassCastException.
00039 *
00040 * TypedHolder is not for general use, instead it is a convenience handle type
00041 * which can be used for container like classes, which need to be able to
00042 * contain both Handles and Views.
00043 *
00044 * As with TypedHandles, TypedHolders are not thread-safe, and should not be
00045 * used in a multi-threaded context even if protected by external
00046 * synchronization. They should only be used as local variables. The most
00047 * common place where thread-safe holders are needed is for object data
00048 * members. For these cases the Coherence API includes a thread-safe variant
00049 * MemberHolder.
00050 *
00051 * @author mf  2008.01.09
00052 *
00053 * @see MemberHolder
00054 * @see WeakHolder
00055 * @see FinalHolder
00056 */
00057 template<class T>
00058 class TypedHolder
00059     : public ChainedHandleElement
00060     {
00061     // ----- typedefs -------------------------------------------------------
00062 
00063     public:
00064         /**
00065         * The type of the values the holder can reference.
00066         */
00067         typedef const 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     // -------- constructors ------------------------------------------------
00081 
00082     public:
00083         /**
00084         * Construct a new TypedHolder referencing NULL via a handle.
00085         */
00086         TypedHolder()
00087             : ChainedHandleElement(/*fView*/ false), m_cpo(NULL)
00088             {
00089             }
00090 
00091         /**
00092         * Construct a new TypedHolder referencing the same Object (and in
00093         * the same manner) as the specified TypedHolder.
00094         *
00095         * @param that  the TypedHolder to initialize from
00096         */
00097         TypedHolder(const TypedHolder& that)
00098             : ChainedHandleElement(that, that.m_fView), m_cpo(that.m_cpo)
00099             {
00100             }
00101 
00102         /**
00103         * Construct a new TypedHolder referencing specified Object via a
00104         * Handle or View.
00105         *
00106         * As a Handle is used, the TypedHolder can be used with the
00107         * cast<...::Handle>() method to retrieve the Handle from the Holder.
00108         *
00109         * @param that  a Handle or View to the Object to reference
00110         */
00111         template<class DT> TypedHolder(const TypedHandle<DT>& that)
00112             : ChainedHandleElement(that, constness<DT>::applied),
00113               m_cpo(get_pointer(that))
00114             {
00115             }
00116 
00117         /**
00118         * Construct a new TypedHolder referencing the same Object (and in
00119         * the same manner) as the specified TypedHolder.
00120         *
00121         * @param that  the TypedHolder to initialize from
00122         */
00123         template<class DT> TypedHolder(const TypedHolder<DT>& that)
00124             : ChainedHandleElement(that, that.m_fView), m_cpo(that.m_cpo)
00125             {
00126             }
00127 
00128         /**
00129         * Construct a new TypedHolder referencing the supplied object.
00130         *
00131         * This method is primarily intended to support assignment from NULL,
00132         * though it will work with other pointers.
00133         *
00134         * @param po  pointer to the Object to reference
00135         */
00136         TypedHolder(T* po)
00137             : ChainedHandleElement(/*fView*/ false),
00138               m_cpo(po == NULL || po->_attach(/*fEscaped*/ false) == NULL
00139                       ? NULL : po)
00140             {
00141             }
00142 
00143         /**
00144         * Construct a new TypedHolder referencing the supplied object.
00145         *
00146         * @param po  pointer to the Object to reference
00147         */
00148         template<class DT> TypedHolder(DT* po)
00149             : ChainedHandleElement(/*fView*/ constness<DT>::applied),
00150               m_cpo(po == NULL || po->_attach(/*fEscaped*/ false) == NULL
00151                       ? NULL : po)
00152             {
00153             }
00154 
00155         /**
00156         * Destroy the TypedHolder.
00157         */
00158         ~TypedHolder()
00159             {
00160             Action nAction = unlink();
00161             if (m_cpo && nAction != action_none)
00162                 {
00163                 performAction(nAction);
00164                 }
00165             }
00166 
00167 
00168     // ----- operators ------------------------------------------------------
00169 
00170     public:
00171         /**
00172         * Assign this TypedHolder to reference the same Object (and in the
00173         * same manner) as the specified TypedHolder.
00174         *
00175         * @param that  the TypedHolder to assign from
00176         *
00177         * @return a reference to this TypedHolder
00178         */
00179         TypedHolder& operator=(const TypedHolder& that)
00180             {
00181             set(get_pointer(that), that.m_fView, that);
00182             return *this;
00183             }
00184 
00185         /**
00186         * Assign this TypedHolder to reference the same Object (and in the
00187         * same manner) as the specified TypedHolder.
00188         *
00189         * @param that  the TypedHolder to assign from
00190         *
00191         * @return a reference to this TypedHolder
00192         */
00193         template<class DT> TypedHolder& operator=(const TypedHolder<DT>& that)
00194             {
00195             set(get_pointer(that), that.m_fView, that);
00196             return *this;
00197             }
00198 
00199         /**
00200         * Return a View to the referenced Object.
00201         *
00202         * @return a View to the referenced Object
00203         */
00204         template<class PT>
00205         operator TypedHandle<const PT>() const
00206             {
00207             return TypedHandle<const PT>(m_cpo, *this);
00208             }
00209 
00210         /**
00211         * Dereference this holder, returning <tt>T&</tt>.
00212         *
00213         * @return a raw <tt>T&</tt> reference to the referenced Object
00214         *
00215         * @throws NullPointerException if the this holder is @c NULL
00216         */
00217         const T& operator*() const
00218             {
00219             const T* po = m_cpo;
00220             if (NULL == po)
00221                 {
00222                 coh_throw_npe(typeid(T));
00223                 }
00224             return *po;
00225             }
00226 
00227         /**
00228         * Dereference the TypedHolder.
00229         *
00230         * @return a const pointer to the referenced Object
00231         */
00232         const T* operator->() const
00233             {
00234             const T* po = m_cpo;
00235             if (NULL == po)
00236                 {
00237                 coh_throw_npe(typeid(T));
00238                 }
00239             return po;
00240             }
00241 
00242 
00243     // ----- helper methods -------------------------------------------------
00244 
00245     protected:
00246         /**
00247         * Return true if the holder contains a handle
00248         *
00249         * @return true iff the holder contains a handle
00250         */
00251         bool isHandle() const
00252             {
00253             return m_fView == false;
00254             }
00255 
00256         /**
00257         * Return a Handle to the referenced Object.
00258         *
00259         * @return a Handle to the referenced Object, or NULL if the Object is
00260         *         referenced via a View
00261         */
00262         TypedHandle<T> getHandle() const
00263             {
00264             if (m_fView)
00265                 {
00266                 return NULL;
00267                 }
00268             // chain new handle from this
00269             return TypedHandle<T>(const_cast<T*>(m_cpo), *this);
00270             }
00271 
00272         /**
00273         * Set the Holder to reference an Object via a Handle.
00274         *
00275         * @param h  the Handle to the Object to reference
00276         */
00277         void set(const T* cp, bool fView, const ChainedHandleElement& that)
00278             {
00279             // link to the new
00280             Action nAction = link(that);
00281             if (m_cpo && nAction != action_none)
00282                 {
00283                 performAction(nAction);
00284                 }
00285             m_cpo   = cp;
00286             m_fView = fView;
00287             }
00288 
00289         /**
00290         * Perform the specified action.
00291         *
00292         * @param nAction  the action to perform
00293         */
00294         void performAction(Action nAction)
00295             {
00296             switch (nAction)
00297                 {
00298                 case action_flip:
00299                     m_cpo->_attach(/*fEscaped*/ false);
00300                     // fall through
00301                 case action_detach:
00302                     if (m_fView)
00303                         {
00304                         m_cpo->_detach(/*fEscaped*/ false);
00305                         }
00306                     else
00307                         {
00308                         const_cast<T*>(m_cpo)->_detach(/*fEscaped*/ false);
00309                         }
00310                     // fall through
00311                 case action_none:
00312                 default:
00313                     break;
00314                 }
00315             }
00316 
00317 
00318     // ----- data members ---------------------------------------------------
00319 
00320     protected:
00321         /**
00322         * The referenced Object.
00323         */
00324         const T* m_cpo;
00325 
00326 
00327     // ----- friends --------------------------------------------------------
00328 
00329     /**
00330     * @internal
00331     */
00332     template<class O> friend const O* get_pointer(const TypedHolder<O>& th);
00333 
00334     /**
00335     * @internal
00336     */
00337     template<class O> friend bool is_handle(const TypedHolder<O>& th);
00338 
00339     /**
00340     * @internal
00341     */
00342     template<class D, class H> friend D cast(const TypedHolder<H>& th,
00343             bool fTest);
00344 
00345     /**
00346     * @internal
00347     */
00348     template<class> friend class TypedHolder;
00349 
00350     /**
00351     * @internal
00352     */
00353     template<class> friend class MemberHolder;
00354     };
00355 
00356 
00357 // ----- non-member operators and functions ---------------------------------
00358 
00359 /**
00360 * Output a human-readable description of the given TypedHolder to the
00361 * specified stream.
00362 *
00363 * @param out  the stream used to output the description
00364 * @param th   the TypedHolder to describe
00365 *
00366 * @return the supplied stream
00367 */
00368 template <typename Char, typename Traits, class T>
00369 COH_INLINE std::basic_ostream<Char, Traits>& operator<<(std::basic_ostream<Char, Traits>& out,
00370         const TypedHolder<T>& th)
00371     {
00372     out << (typename T::View) th;
00373     return out;
00374     }
00375 
00376 /**
00377 * @internal
00378 *
00379 * Return the pointer associated with the TypedHolder.
00380 *
00381 * The lifetime of the Object referenced by the returned pointer
00382 * cannot be guaranteed beyond the lifetime of the Holder from
00383 * which it was obtained. Additionally if the associated handle is reassigned
00384 * the lifetime of the referenced Object is also undefined.
00385 *
00386 * @param th the Holder to used in retrieving the pointer.
00387 *
00388 * @return the pointer associated with the TypedHolder.
00389 */
00390 template<class T>
00391 const T* get_pointer(const TypedHolder<T>& th)
00392     {
00393     return th.m_cpo;
00394     }
00395 
00396 /**
00397 * Assign the specified holder to NULL.
00398 *
00399 * @param th the holder to clear
00400 */
00401 template<class T> void clear_handle(TypedHolder<T>& th)
00402     {
00403     th = NULL;
00404     }
00405 
00406 /**
00407 * Return true if the supplied holder equals NULL.
00408 *
00409 * @param th  the holder to test
00410 *
00411 * @return true iff the supplied holder equals NULL
00412 */
00413 template<class T>
00414 bool is_null(const TypedHolder<T>& th)
00415     {
00416     return th == NULL;
00417     }
00418 
00419 /**
00420 * Return true if the supplied holder contains a handle
00421 *
00422 * @param th  the holder to test
00423 *
00424 * @return true iff the supplied holder contains a handle
00425 */
00426 template<class T>
00427 bool is_handle(const TypedHolder<T>& th)
00428     {
00429     return th.isHandle();
00430     }
00431 
00432 /**
00433 * Perform a dynamic cast the pointer associated with the TypedHolder
00434 * to a the specified handle/view type.
00435 *
00436 * @param th      the TypedHolder from which to perform the cast
00437 * @param fThrow  true if an exception is to be thrown on a failed cast
00438 *
00439 * @return the casted pointer, or NULL if the cast fails and fThrow is false
00440 *
00441 * @throws ClassCastException if the cast fails and fThrow is true
00442 */
00443 template<class D, class T>
00444 D cast(const TypedHolder<T>& th, bool fThrow = true)
00445     {
00446     TypedHandle<T> h = th.getHandle();
00447     if (NULL == h)
00448         {
00449         TypedHandle<const T> v = th;
00450 
00451         if (NULL == v)
00452             {
00453             // from NULL to any type is allowed
00454             return D(); // NULL
00455             }
00456 
00457         // input is a non-NULL view
00458         if (constness<typename D::ValueType>::applied)
00459             {
00460             // input type is a holder(view), output type is a view or holder
00461             // return a view and let it be converted if necessary to a holder
00462             // producing a holder(handle) can't happen from here, but we've
00463             // already proved that the input type is a view (NULL == h)
00464             TypedHandle<typename D::ValueType> vD(
00465                 (typename D::ValueType*) get_pointer(
00466                         cast<typename D::ValueType::View>(v, fThrow)), v);
00467             return vD;
00468             }
00469         else
00470             {
00471             // output type is a handle; input type is a view (error)
00472             if (fThrow)
00473                 {
00474                 coh_throw_const_cast(typeid(typename D::ValueType), typeid(*th));
00475                 }
00476             return D(); // NULL
00477             }
00478         }
00479 
00480     // input type is a holder(handle), output type can be handle/view/holder;
00481     // cast from on the handle, and allow conversion to produce expected
00482     // result type
00483     return cast<typename D::ValueType::Handle>(h, fThrow);
00484     }
00485 
00486 /**
00487 * Perform an instanceof check on a handle or view.
00488 *
00489 * @param th  the TypedHolder from which to perform the test
00490 *
00491 * @return true if the supplied handle is an instance of the specified type
00492 */
00493 template<class D, class T>
00494 bool instanceof(const TypedHolder<T>& th)
00495     {
00496     return NULL !=th && NULL != cast<D>(th, false);
00497     }
00498 
00499 COH_CLOSE_NAMESPACE2
00500 
00501 #endif // COH_TYPED_HOLDER_HPP
Copyright © 2000, 2017, Oracle and/or its affiliates. All rights reserved.