//////////////////////////////////////////////////////////////////////////////// // The Loki Library // Copyright (c) 2006 by Guillaume Chatelet // // Code covered by the MIT License // // Permission to use, copy, modify, distribute and sell this software for any // purpose is hereby granted without fee, provided that the above copyright // notice appear in all copies and that both that copyright notice and this // permission notice appear in supporting documentation. // // The authors make no representations about the suitability of this software // for any purpose. It is provided "as is" without express or implied warranty. // // This code DOES NOT accompany the book: // Alexandrescu, Andrei. "Modern C++ Design: Generic Programming and Design // Patterns Applied". Copyright (c) 2001. Addison-Wesley. // //////////////////////////////////////////////////////////////////////////////// // $Id$ #ifndef SPCACHEDFACTORY_H_ #define SPCACHEDFACTORY_H_ /** * This file is intented to be used if you want a CachedFactory with * a SmartPointer encapsulation policy. * It as been defined in a separate file because of the many introduced * dependencies (SmartPtr.h would depend on Functor.h and CachedFactory.h * would depend on SmartPtr.h). By defining another header you pay for those * extra dependencies only if you need it. * * This file defines FunctionStorage a new SmartPointer storage policy and * SmartPointer a new CachedFactory encapsulation policy. */ #include #include #include namespace Loki { //////////////////////////////////////////////////////////////////////////////// /// \class FunctionStorage /// /// \ingroup SmartPointerStorageGroup /// \brief Implementation of the StoragePolicy used by SmartPtr. /// /// This storage policy is used by SmartPointer CachedFactory's encapsulation /// policy. It's purpose is to call a Functor instead of deleting the /// underlying pointee object. You have to set the callback functor by calling /// SetCallBackFunction(const FunctorType &functor). /// /// Unfortunately, the functor argument is not a reference to the SmartPtr but /// a void *. Making functor argument a reference to the pointer would require /// the FunctionStorage template to know the full definition of the SmartPtr. //////////////////////////////////////////////////////////////////////////////// template class FunctionStorage { public: /// the type of the pointee_ object typedef T* StoredType; /// type used to declare OwnershipPolicy type. typedef T* InitPointerType; /// type returned by operator-> typedef T* PointerType; /// type returned by operator* typedef T& ReferenceType; /// type of the Functor to set typedef Functor< void , Seq< void* > > FunctorType; FunctionStorage() : pointee_(Default()), functor_() {} // The storage policy doesn't initialize the stored pointer // which will be initialized by the OwnershipPolicy's Clone fn FunctionStorage(const FunctionStorage& rsh) : pointee_(0), functor_(rsh.functor_) {} template FunctionStorage(const FunctionStorage& rsh) : pointee_(0), functor_(rsh.functor_) {} FunctionStorage(const StoredType& p) : pointee_(p), functor_() {} PointerType operator->() const { return pointee_; } ReferenceType operator*() const { return *pointee_; } void Swap(FunctionStorage& rhs) { std::swap(pointee_, rhs.pointee_); std::swap(functor_, rhs.functor_); } /// Sets the callback function to call. You have to specify it or /// the smartPtr will throw a bad_function_call exception. void SetCallBackFunction(const FunctorType &functor) { functor_ = functor; } // Accessors template friend typename FunctionStorage::PointerType GetImpl(const FunctionStorage& sp); template friend const typename FunctionStorage::StoredType& GetImplRef(const FunctionStorage& sp); template friend typename FunctionStorage::StoredType& GetImplRef(FunctionStorage& sp); protected: // Destroys the data stored // (Destruction might be taken over by the OwnershipPolicy) void Destroy() { functor_(this); } // Default value to initialize the pointer static StoredType Default() { return 0; } private: // Data StoredType pointee_; FunctorType functor_; }; template inline typename FunctionStorage::PointerType GetImpl(const FunctionStorage& sp) { return sp.pointee_; } template inline const typename FunctionStorage::StoredType& GetImplRef(const FunctionStorage& sp) { return sp.pointee_; } template inline typename FunctionStorage::StoredType& GetImplRef(FunctionStorage& sp) { return sp.pointee_; } /** * \class SmartPointer * \ingroup EncapsulationPolicyCachedFactoryGroup * \brief Encapsulate the object in a SmartPtr with FunctionStorage policy. * * The object will come back to the Cache as soon as no more SmartPtr are * referencing this object. You can customize the SmartPointer with the standard * SmartPtr policies (OwnershipPolicy, ConversionPolicy, CheckingPolicy, * ConstnessPolicy) but StoragePolicy is forced to FunctionStorage. */ template < class AbstractProduct, template class OwnershipPolicy = RefCounted, class ConversionPolicy = DisallowConversion, template class CheckingPolicy = AssertCheck, template class ConstnessPolicy = LOKI_DEFAULT_CONSTNESS > class SmartPointer { private: typedef SmartPtr< AbstractProduct,OwnershipPolicy, ConversionPolicy, CheckingPolicy, FunctionStorage, ConstnessPolicy > CallBackSP; protected: typedef CallBackSP ProductReturn; SmartPointer() : fun(this, &SmartPointer::smartPointerCallbackFunction) {} virtual ~SmartPointer(){} ProductReturn encapsulate(AbstractProduct* pProduct) { CallBackSP SP(pProduct); SP.SetCallBackFunction(fun); return SP; } AbstractProduct* release(ProductReturn &pProduct) { return GetImpl(pProduct); } const char* name(){return "smart pointer";} private: SmartPointer& operator=(const SmartPointer&); SmartPointer(const SmartPointer&); void smartPointerCallbackFunction(void* pSP) { CallBackSP &SP(*reinterpret_cast(pSP)); ReleaseObject(SP); } virtual void ReleaseObject(ProductReturn &object)=0; const typename CallBackSP::FunctorType fun; }; } // namespace Loki #endif /*SPCACHEDFACTORY_H_*/