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

E26041-01

coherence/lang/TypedHolder.hpp

00001 /*
00002 * TypedHolder.hpp
00003 *
00004 * Copyright (c) 2000, 2013, 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 (nAction != action_none)
00160                 {
00161                 safeDestruct(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 (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             const T* cpo = m_cpo;
00295             switch (nAction)
00296                 {
00297                 case action_error:
00298                     coh_throw_illegal_state("corrupted ChainedHandleElement");
00299                 case action_flip:
00300                     if (NULL != cpo) cpo->_attach(/*fEscaped*/ false);
00301                     // fall through
00302                 case action_detach:
00303                     if (NULL != cpo)
00304                         {
00305                         if (m_fView)
00306                             {
00307                             cpo->_detach(/*fEscaped*/ false);
00308                             }
00309                         else
00310                             {
00311                             const_cast<T*>(cpo)->_detach(/*fEscaped*/ false);
00312                             }
00313                         }
00314                     // fall through
00315                 case action_none:
00316                 default:
00317                     break;
00318                 }
00319             }
00320 
00321         /**
00322         * Destruct the handle.
00323         *
00324         * Any exception occurring during distribution will simply be printed,
00325         * the intent of this function is for use during TypedHandle
00326         * destruction. It is not the common path and is pulled out to
00327         * encourage inlining of the destructor.
00328         */
00329         void safeDestruct(Action nAction)
00330             {
00331             try
00332                 {
00333                 performAction(nAction);
00334                 }
00335             catch (const std::exception& e)
00336                 {
00337                 // Exception::View is not a known type within this file
00338                 std::cerr << "Error during ~TypedHolder: " << e.what() << std::endl;
00339                 return; // can't re-throw from within destructor
00340                 }
00341             }
00342 
00343     // ----- data members ---------------------------------------------------
00344 
00345     protected:
00346         /**
00347         * The referenced Object.
00348         */
00349         const T* m_cpo;
00350 
00351 
00352     // ----- friends --------------------------------------------------------
00353 
00354     /**
00355     * @internal
00356     */
00357     template<class O> friend const O* get_pointer(const TypedHolder<O>& th);
00358 
00359     /**
00360     * @internal
00361     */
00362     template<class O> friend bool is_handle(const TypedHolder<O>& th);
00363 
00364     /**
00365     * @internal
00366     */
00367     template<class D, class H> friend D cast(const TypedHolder<H>& th,
00368             bool fTest);
00369 
00370     /**
00371     * @internal
00372     */
00373     template<class> friend class TypedHolder;
00374 
00375     /**
00376     * @internal
00377     */
00378     template<class> friend class MemberHolder;
00379     };
00380 
00381 
00382 // ----- non-member operators and functions ---------------------------------
00383 
00384 /**
00385 * Output a human-readable description of the given TypedHolder to the
00386 * specified stream.
00387 *
00388 * @param out  the stream used to output the description
00389 * @param th   the TypedHolder to describe
00390 *
00391 * @return the supplied stream
00392 */
00393 template<class T> std::ostream& operator<<(std::ostream& out,
00394         const TypedHolder<T>& th)
00395     {
00396     out << (typename T::View) th;
00397     return out;
00398     }
00399 
00400 /**
00401 * @internal
00402 *
00403 * Return the pointer associated with the TypedHolder.
00404 *
00405 * The lifetime of the Object referenced by the returned pointer
00406 * cannot be guaranteed beyond the lifetime of the Holder from
00407 * which it was obtained. Additionally if the associated handle is reassigned
00408 * the lifetime of the referenced Object is also undefined.
00409 *
00410 * @param th the Holder to used in retrieving the pointer.
00411 *
00412 * @return the pointer associated with the TypedHolder.
00413 */
00414 template<class T>
00415 const T* get_pointer(const TypedHolder<T>& th)
00416     {
00417     return th.m_cpo;
00418     }
00419 
00420 /**
00421 * Assign the specified holder to NULL.
00422 *
00423 * @param th the holder to clear
00424 */
00425 template<class T> void clear_handle(TypedHolder<T>& th)
00426     {
00427     th = NULL;
00428     }
00429 
00430 /**
00431 * Return true if the supplied holder equals NULL.
00432 *
00433 * @param th  the holder to test
00434 *
00435 * @return true iff the supplied holder equals NULL
00436 */
00437 template<class T>
00438 bool is_null(const TypedHolder<T>& th)
00439     {
00440     return th == NULL;
00441     }
00442 
00443 /**
00444 * Return true if the supplied holder contains a handle
00445 *
00446 * @param th  the holder to test
00447 *
00448 * @return true iff the supplied holder contains a handle
00449 */
00450 template<class T>
00451 bool is_handle(const TypedHolder<T>& th)
00452     {
00453     return th.isHandle();
00454     }
00455 
00456 /**
00457 * Perform a dynamic cast the pointer associated with the TypedHolder
00458 * to a the specified handle/view type.
00459 *
00460 * @param th      the TypedHolder from which to perform the cast
00461 * @param fThrow  true if an exception is to be thrown on a failed cast
00462 *
00463 * @return the casted pointer, or NULL if the cast fails and fThrow is false
00464 *
00465 * @throws ClassCastException if the cast fails and fThrow is true
00466 */
00467 template<class D, class T>
00468 D cast(const TypedHolder<T>& th, bool fThrow = true)
00469     {
00470     TypedHandle<T> h = th.getHandle();
00471     if (NULL == h)
00472         {
00473         TypedHandle<const T> v = th;
00474 
00475         if (NULL == v)
00476             {
00477             // from NULL to any type is allowed
00478             return D(); // NULL
00479             }
00480 
00481         // input is a non-NULL view
00482         if (constness<typename D::ValueType>::applied)
00483             {
00484             // input type is a holder(view), output type is a view or holder
00485             // return a view and let it be converted if necessary to a holder
00486             // producing a holder(handle) can't happen from here, but we've
00487             // already proved that the input type is a view (NULL == h)
00488             TypedHandle<typename D::ValueType> vD(
00489                 (typename D::ValueType*) get_pointer(
00490                         cast<typename D::ValueType::View>(v, fThrow)), v);
00491             return vD;
00492             }
00493         else
00494             {
00495             // output type is a handle; input type is a view (error)
00496             if (fThrow)
00497                 {
00498                 coh_throw_const_cast(typeid(typename D::ValueType), typeid(*th));
00499                 }
00500             return D(); // NULL
00501             }
00502         }
00503 
00504     // input type is a holder(handle), output type can be handle/view/holder;
00505     // cast from on the handle, and allow conversion to produce expected
00506     // result type
00507     return cast<typename D::ValueType::Handle>(h, fThrow);
00508     }
00509 
00510 /**
00511 * Perform an instanceof check on a handle or view.
00512 *
00513 * @param th  the TypedHolder from which to perform the test
00514 *
00515 * @return true if the supplied handle is an instance of the specified type
00516 */
00517 template<class D, class T>
00518 bool instanceof(const TypedHolder<T>& th)
00519     {
00520     return NULL !=th && NULL != cast<D>(th, false);
00521     }
00522 
00523 COH_CLOSE_NAMESPACE2
00524 
00525 #endif // COH_TYPED_HOLDER_HPP
Copyright © 2000, 2013, Oracle and/or its affiliates. All rights reserved.