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