00001 /* 00002 * Managed.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_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 usable 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 life-cycle 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 accessible 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 * @param v the object to compare against 00264 * 00265 * This method delegates to the custom types equality operator. 00266 */ 00267 virtual bool equals(Object::View v) const 00268 { 00269 // NOTE: a build error here indicates that the following function 00270 // has not been defined for T: 00271 // bool operator==(const T&, const T&) 00272 return this == v || 00273 (instanceof<typename cloneable_spec<Managed<T> >::View>(v) && 00274 getManagedObject() == 00275 cast<typename cloneable_spec<Managed<T> >::View>(v) 00276 ->getManagedObject()); 00277 } 00278 00279 /** 00280 * {@inheritDoc} 00281 * 00282 * @param out the stream to write to 00283 * 00284 * This method delegates to the custom types stream operator. (operator<<) 00285 */ 00286 virtual void toStream(std::ostream& out) const 00287 { 00288 // NOTE: a build error here indicates that the following function 00289 // has not been defined for T: 00290 // std::ostream& operator<<(std::ostream&, const T&) 00291 out << getManagedObject(); 00292 } 00293 00294 /** 00295 * {@inheritDoc} 00296 * 00297 * This method delegates to the global hash function specialized 00298 * for the custom type. 00299 */ 00300 virtual size32_t hashCode() const 00301 { 00302 // NOTE: a build error here indicates that the following function 00303 // has not been defined for T: 00304 // size_t hash_value(const T&) 00305 return size32_t(hash_value(*this)); 00306 } 00307 00308 00309 // ----- memory management ---------------------------------------------- 00310 00311 protected: 00312 /** 00313 * @internal 00314 * 00315 * Explicitly delegate to Coherence Object to remove ambiguity 00316 * for managed classes which inherit some other new(). 00317 */ 00318 static void* operator new(size_t cb) 00319 { 00320 return Object::operator new(cb); 00321 } 00322 00323 /** 00324 * @internal 00325 * 00326 * Explicitly delegate to Coherence Object to remove ambiguity 00327 * for managed classes which inherit some other delete(). 00328 */ 00329 static void operator delete(void* po) 00330 { 00331 Object::operator delete(po); 00332 } 00333 }; 00334 00335 00336 // ----- non-member operators and functions --------------------------------- 00337 00338 /** 00339 * Output a human-readable description of the specified Managed<T> to the given 00340 * stream. 00341 * 00342 * @param out the stream used to output the description 00343 * @param aT the Managed<T> to describe 00344 * 00345 * @return the supplied stream 00346 */ 00347 template<class T> std::ostream& operator<<(std::ostream& out, const Managed<T>& aT) 00348 { 00349 return coherence::lang::operator<<(out, (const Object&) aT); 00350 } 00351 00352 COH_CLOSE_NAMESPACE2 00353 00354 #endif // COH_MANAGED_HPP