1 //////////////////////////////////////////////////////////////////////////////// 2 // The Loki Library 3 // Copyright (c) 2006 by Guillaume Chatelet 4 // 5 // Code covered by the MIT License 6 // 7 // Permission to use, copy, modify, distribute and sell this software for any 8 // purpose is hereby granted without fee, provided that the above copyright 9 // notice appear in all copies and that both that copyright notice and this 10 // permission notice appear in supporting documentation. 11 // 12 // The authors make no representations about the suitability of this software 13 // for any purpose. It is provided "as is" without express or implied warranty. 14 // 15 // This code DOES NOT accompany the book: 16 // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design 17 // Patterns Applied". Copyright (c) 2001. Addison-Wesley. 18 // 19 //////////////////////////////////////////////////////////////////////////////// 20 21 // $Id: SPCachedFactory.h 896 2008-08-08 22:20:05Z syntheticpp $ 22 23 #ifndef SPCACHEDFACTORY_H_ 24 #define SPCACHEDFACTORY_H_ 25 26 /** 27 * This file is intented to be used if you want a CachedFactory with 28 * a SmartPointer encapsulation policy. 29 * It as been defined in a separate file because of the many introduced 30 * dependencies (SmartPtr.h would depend on Functor.h and CachedFactory.h 31 * would depend on SmartPtr.h). By defining another header you pay for those 32 * extra dependencies only if you need it. 33 * 34 * This file defines FunctionStorage a new SmartPointer storage policy and 35 * SmartPointer a new CachedFactory encapsulation policy. 36 */ 37 38 #include <loki/Functor.h> 39 #include <loki/SmartPtr.h> 40 #include <loki/CachedFactory.h> 41 42 namespace Loki 43 { 44 45 //////////////////////////////////////////////////////////////////////////////// 46 /// \class FunctionStorage 47 /// 48 /// \ingroup SmartPointerStorageGroup 49 /// \brief Implementation of the StoragePolicy used by SmartPtr. 50 /// 51 /// This storage policy is used by SmartPointer CachedFactory's encapsulation 52 /// policy. It's purpose is to call a Functor instead of deleting the 53 /// underlying pointee object. You have to set the callback functor by calling 54 /// SetCallBackFunction(const FunctorType &functor). 55 /// 56 /// Unfortunately, the functor argument is not a reference to the SmartPtr but 57 /// a void *. Making functor argument a reference to the pointer would require 58 /// the FunctionStorage template to know the full definition of the SmartPtr. 59 //////////////////////////////////////////////////////////////////////////////// 60 61 template <class T> 62 class FunctionStorage 63 { 64 public: 65 /// the type of the pointee_ object 66 typedef T* StoredType; 67 /// type used to declare OwnershipPolicy type. 68 typedef T* InitPointerType; 69 /// type returned by operator-> 70 typedef T* PointerType; 71 /// type returned by operator* 72 typedef T& ReferenceType; 73 /// type of the Functor to set 74 typedef Functor< void , Seq< void* > > FunctorType; 75 FunctionStorage()76 FunctionStorage() : pointee_(Default()), functor_() 77 {} 78 79 // The storage policy doesn't initialize the stored pointer 80 // which will be initialized by the OwnershipPolicy's Clone fn FunctionStorage(const FunctionStorage & rsh)81 FunctionStorage(const FunctionStorage& rsh) : pointee_(0), functor_(rsh.functor_) 82 {} 83 84 template <class U> FunctionStorage(const FunctionStorage<U> & rsh)85 FunctionStorage(const FunctionStorage<U>& rsh) : pointee_(0), functor_(rsh.functor_) 86 {} 87 FunctionStorage(const StoredType & p)88 FunctionStorage(const StoredType& p) : pointee_(p), functor_() {} 89 90 PointerType operator->() const { return pointee_; } 91 92 ReferenceType operator*() const { return *pointee_; } 93 Swap(FunctionStorage & rhs)94 void Swap(FunctionStorage& rhs) 95 { 96 std::swap(pointee_, rhs.pointee_); 97 std::swap(functor_, rhs.functor_); 98 } 99 100 /// Sets the callback function to call. You have to specify it or 101 /// the smartPtr will throw a bad_function_call exception. SetCallBackFunction(const FunctorType & functor)102 void SetCallBackFunction(const FunctorType &functor) 103 { 104 functor_ = functor; 105 } 106 107 // Accessors 108 template <class F> 109 friend typename FunctionStorage<F>::PointerType GetImpl(const FunctionStorage<F>& sp); 110 111 template <class F> 112 friend const typename FunctionStorage<F>::StoredType& GetImplRef(const FunctionStorage<F>& sp); 113 114 template <class F> 115 friend typename FunctionStorage<F>::StoredType& GetImplRef(FunctionStorage<F>& sp); 116 117 protected: 118 // Destroys the data stored 119 // (Destruction might be taken over by the OwnershipPolicy) Destroy()120 void Destroy() 121 { 122 functor_(this); 123 } 124 125 // Default value to initialize the pointer Default()126 static StoredType Default() 127 { return 0; } 128 129 private: 130 // Data 131 StoredType pointee_; 132 FunctorType functor_; 133 }; 134 135 template <class T> GetImpl(const FunctionStorage<T> & sp)136 inline typename FunctionStorage<T>::PointerType GetImpl(const FunctionStorage<T>& sp) 137 { return sp.pointee_; } 138 139 template <class T> GetImplRef(const FunctionStorage<T> & sp)140 inline const typename FunctionStorage<T>::StoredType& GetImplRef(const FunctionStorage<T>& sp) 141 { return sp.pointee_; } 142 143 template <class T> GetImplRef(FunctionStorage<T> & sp)144 inline typename FunctionStorage<T>::StoredType& GetImplRef(FunctionStorage<T>& sp) 145 { return sp.pointee_; } 146 147 /** 148 * \class SmartPointer 149 * \ingroup EncapsulationPolicyCachedFactoryGroup 150 * \brief Encapsulate the object in a SmartPtr with FunctionStorage policy. 151 * 152 * The object will come back to the Cache as soon as no more SmartPtr are 153 * referencing this object. You can customize the SmartPointer with the standard 154 * SmartPtr policies (OwnershipPolicy, ConversionPolicy, CheckingPolicy, 155 * ConstnessPolicy) but StoragePolicy is forced to FunctionStorage. 156 */ 157 template 158 < 159 class AbstractProduct, 160 template <class> class OwnershipPolicy = RefCounted, 161 class ConversionPolicy = DisallowConversion, 162 template <class> class CheckingPolicy = AssertCheck, 163 template<class> class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS 164 > 165 class SmartPointer 166 { 167 private: 168 typedef SmartPtr< AbstractProduct,OwnershipPolicy, 169 ConversionPolicy, CheckingPolicy, 170 FunctionStorage, ConstnessPolicy > CallBackSP; 171 protected: 172 typedef CallBackSP ProductReturn; SmartPointer()173 SmartPointer() : fun(this, &SmartPointer::smartPointerCallbackFunction) {} ~SmartPointer()174 virtual ~SmartPointer(){} 175 encapsulate(AbstractProduct * pProduct)176 ProductReturn encapsulate(AbstractProduct* pProduct) 177 { 178 CallBackSP SP(pProduct); 179 SP.SetCallBackFunction(fun); 180 return SP; 181 } 182 release(ProductReturn & pProduct)183 AbstractProduct* release(ProductReturn &pProduct) 184 { 185 return GetImpl(pProduct); 186 } 187 name()188 const char* name(){return "smart pointer";} 189 190 private: 191 SmartPointer& operator=(const SmartPointer&); 192 SmartPointer(const SmartPointer&); smartPointerCallbackFunction(void * pSP)193 void smartPointerCallbackFunction(void* pSP) 194 { 195 CallBackSP &SP(*reinterpret_cast<CallBackSP*>(pSP)); 196 ReleaseObject(SP); 197 } 198 virtual void ReleaseObject(ProductReturn &object)=0; 199 const typename CallBackSP::FunctorType fun; 200 }; 201 202 } // namespace Loki 203 204 #endif /*SPCACHEDFACTORY_H_*/ 205