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