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

E47891-01

coherence/lang/TypedHolder.hpp

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