coherence/lang/Managed.hpp

00001 /*
00002 * Managed.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_MANAGED_HPP
00017 #define COH_MANAGED_HPP
00018 
00019 #include "coherence/lang/compatibility.hpp"
00020 
00021 #include "coherence/lang/Object.hpp"
00022 
00023 #include <cstddef>
00024 #include <ostream>
00025 #include <functional>
00026 
00027 COH_OPEN_NAMESPACE2(coherence,lang)
00028 
00029 
00030 /**
00031 * Managed is an adaptor class which transforms a pre-existing class into a
00032 * Coherence managed Object.
00033 *
00034 * The resulting object will be useable both as the supplied data type and as a
00035 * Coherence managed object. As a managed object it is suitable for storage in
00036 * Coherence caches.
00037 *
00038 * The managed object must be created using its associated static create
00039 * methods, which support either default construction, or copy construction
00040 * from the custom type. The managed object's lifecycle is dictated by reference
00041 * counting, and it may not be manually deleted.
00042 *
00043 * To be compatible with the Managed template the following set of functions
00044 * must be defined for the supplied type:
00045 * <ul>
00046 *   <li>zero parameter constructor (public or protected):
00047 *       <code>CustomType::CustomType()</code></li>
00048 *   <li>copy constructor (public or protected):
00049 *       <code>CustomType::CustomType(const CustomType&)</code></li>
00050 *   <li>equality comparison operator:
00051 *       <code>bool operator==(const CustomType&, const CustomType&)</code>
00052 *   <li>ostream output function:
00053 *       <code>std::ostream& operator<<(std::ostream&, const CustomType&)</code></li>
00054 *   <li>hash function:
00055 *       <code>size_t hash_value(const CustomType&)</code></li>
00056 * </ul>
00057 *
00058 * A example of a conforming class would be:
00059 * @code
00060 * class Address
00061 *   {
00062 *   public:
00063 *     Address(const std::string& sCity, const std::String& sState, int nZip)
00064 *       : m_sCity(sCity), m_sState(sState), m_nZip(nZip) {}
00065 *
00066 *     Address(const Address& that)
00067 *       : m_sCity(that.m_sCity), m_sState(that.m_sState), m_nZip(that.m_nZip) {}
00068 *
00069 *   protected:
00070 *     Address()
00071 *       : m_nZip(0) {}
00072 *
00073 *   public:
00074 *     std::string  getCity()  const {return m_sCity;}
00075 *     std::string  getState() const {return m_sState;}
00076 *     int          getZip()   const {return m_nZip;}
00077 *
00078 *   private:
00079 *     const std::string m_sCity;
00080 *     const std::string m_sState;
00081 *     const int         m_nZip;
00082 *   };
00083 *
00084 * bool operator==(const Address& addra, const Address& addrb)
00085 *   {
00086 *   return addra.getZip()   == addrb.getZip() &&
00087 *          addra.getState() == addrb.getState() &&
00088 *          addra.getCity()  == addrb.getCity();
00089 *   }
00090 *
00091 * std::ostream& operator<<(std::ostream& out, const Address& addr)
00092 *   {
00093 *   out << addr.getCity() << ", " << addr.getState() << "  " << addr.getZip();
00094 *   return out;
00095 *   }
00096 *
00097 * size_t hash_value(const Address& addr)
00098 *   {
00099 *   return (size_t) addr.getZip();
00100 *   }
00101 * @endcode
00102 *
00103 * Serialization support may be added by specializing the following free-functions:
00104 * <ul>
00105 *   <li>serializer:
00106 *       <code>void serialize<CustomType>(coherence::io::pof::PofWriter::Handle, const CustomType&)</code></li>
00107 *   <li>deserializer:
00108 *       <code>CustomType deserialize<CustomType>(coherence::io::pof::PofReader::Handle)</code></li>
00109 * </ul>
00110 *
00111 * The serialization functions do not need to be defined within the source file
00112 * of the original data type. They only need to be linked into the application,
00113 * and registered with the SystemPofContext via the COH_REGISTER_MANAGED_CLASS
00114 * macro.
00115 *
00116 * @code
00117 * #include "coherence/io/pof/SystemPofContext.hpp"
00118 *
00119 * #include "Address.hpp"
00120 *
00121 * using namespace coherence::io::pof;
00122 *
00123 * COH_REGISTER_MANAGED_CLASS(1234, Address);
00124 *
00125 * template<> void serialize<Address>(PofWriter::Handle hOut, const Address& addr)
00126 *   {
00127 *   hOut->writeString(0, addr.getCity());
00128 *   hOut->writeString(1, addr.getState());
00129 *   hOut->writeInt32 (2, addr.getZip());
00130 *   }
00131 *
00132 * template<> Address deserialize<Address>(PofReader::Handle hIn)
00133 *   {
00134 *   std::string sCity  = hIn->readString(0);
00135 *   std::string sState = hIn->readString(1);
00136 *   int         nZip   = hIn->readInt32 (2);
00137 *
00138 *   return Address(sCity, sState, nZip);
00139 *   }
00140 * @endcode
00141 *
00142 * An example usage of the resulting managed type would be:
00143 * @code
00144 * // construct the non-managed version as usual
00145 * Address office("Redwood Shores", "CA", 94065);
00146 *
00147 * // the managed version can be initialized from the non-managed version
00148 * // the result is a new object, which does not reference the original
00149 * Managed<Address>::View vOffice = Managed<Address>::create(office);
00150 * String::View           vKey    = "Oracle";
00151 *
00152 * // the managed version is suitable for use with caches
00153 * hCache->put(vKey, vAddr);
00154 * vOffice = cast<Managed<Address>::View>(hCache->get(vKey));
00155 *
00156 * // the non-managed class's public methods/fields remain accessable
00157 * assert(vOffice->getCity()  == office.getCity());
00158 * assert(vOffice->getState() == office.getState());
00159 * assert(vOffice->getZip()   == office.getZip());
00160 *
00161 * // conversion back to the non-managed type may be performed using the
00162 * // non-managed class's copy constructor.
00163 * Address officeOut = *vOffice;
00164 * @endcode
00165 *
00166 * @see coherence::io::pof::PofReader
00167 * @see coherence::io::pof::PofWriter
00168 * @see coherence::io::pof::SystemPofContext
00169 *
00170 * @author mf  2007.07.05
00171 */
00172 template<class T>
00173 class Managed
00174     : public cloneable_spec<Managed<T> >,
00175       public T
00176     {
00177     friend class factory<Managed<T> >;
00178 
00179     // ----- typedefs -------------------------------------------------------
00180 
00181     public:
00182         /**
00183         * The boxed class type.
00184         */
00185         typedef T BoxedType;
00186 
00187 
00188     // ----- constructors ---------------------------------------------------
00189 
00190     protected:
00191         /**
00192         * Create a new Managed<T> instance with the default initial T value.
00193         *
00194         * @return the new Managed<T>
00195         */
00196         Managed()
00197             : T()
00198             {
00199             // NOTE: a build error here indicates a zero-parameter constructor
00200             // has not been defined for T
00201             }
00202 
00203         /**
00204         * Create a new Managed<T> instance.
00205         *
00206         * @param t  the initial value for the templated type
00207         */
00208         Managed(const T& t)
00209             : T(t)
00210             {
00211             // NOTE: a build error here indicates a copy constructor has not
00212             // been defined for T
00213             }
00214 
00215         /**
00216         * Copy constructor.
00217         */
00218         Managed(const Managed<T>& that)
00219             : cloneable_spec<Managed<T> >(that), T(that)
00220             {
00221             // NOTE: a build error here indicates a copy constructor has not
00222             // been defined for T
00223             }
00224 
00225         /**
00226         * @internal
00227         */
00228         virtual ~Managed()
00229             {
00230             }
00231 
00232 
00233     // ----- Managed interface ----------------------------------------------
00234 
00235     protected:
00236         /**
00237         * Return the reference to the managed T object.
00238         *
00239         * @return the managed object
00240         */
00241         virtual T& getManagedObject()
00242             {
00243             return *this;
00244             }
00245 
00246         /**
00247         * Return the constant reference to managed T object.
00248         *
00249         * @return the managed object
00250         */
00251         virtual const T& getManagedObject() const
00252             {
00253             return *this;
00254             }
00255 
00256 
00257     // ----- Object interface -----------------------------------------------
00258 
00259     public:
00260         /**
00261         * {@inheritDoc}
00262         *
00263         * This method delegates to the custom types equality operator.
00264         */
00265         virtual bool equals(Object::View v) const
00266             {
00267             // NOTE: a build error here indicates that the following function
00268             // has not been defined for T:
00269             //   bool operator==(const T&, const T&)
00270             return this == v ||
00271                 (instanceof<typename cloneable_spec<Managed<T> >::View>(v) &&
00272                     getManagedObject() ==
00273                         cast<typename cloneable_spec<Managed<T> >::View>(v)
00274                             ->getManagedObject());
00275             }
00276 
00277         /**
00278         * {@inheritDoc}
00279         *
00280         * This method delegates to the custom types stream opeartor. (operator<<)
00281         */
00282         virtual void toStream(std::ostream& out) const
00283             {
00284             // NOTE: a build error here indicates that the following function
00285             // has not been defined for T:
00286             //   std::ostream& operator<<(std::ostream&, const T&)
00287             out << getManagedObject();
00288             }
00289 
00290         /**
00291         * {@inheritDoc}
00292         *
00293         * This method delegates to the global hash function specialized
00294         * for the custome type.
00295         */
00296         virtual size32_t hashCode() const
00297             {
00298             // NOTE: a build error here indicates that the following function
00299             // has not been defined for T:
00300             //   size_t hash_value(const T&)
00301             return size32_t(hash_value(*this));
00302             }
00303     };
00304 
00305 
00306 // ----- non-member operators and functions ---------------------------------
00307 
00308 /**
00309 * Output a human-readable description of the specified Managed<T> to the given
00310 * stream.
00311 *
00312 * @param out  the stream used to output the description
00313 * @param aT   the Managed<T> to describe
00314 *
00315 * @return the supplied stream
00316 */
00317 template<class T> std::ostream& operator<<(std::ostream& out, const Managed<T>& aT)
00318     {
00319     return coherence::lang::operator<<(out, (const Object&) aT);
00320     }
00321 
00322 COH_CLOSE_NAMESPACE2
00323 
00324 #endif // COH_MANAGED_HPP
Copyright (c) 2000-2008 Oracle. All rights reserved.