From 2b0ea4650bf074257792f1e1d0c13c5ba8044f23 Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 31 Aug 2007 14:57:49 +0200 Subject: [PATCH] reworked factory to get better separation of concerns. But custom allocation can't be done as I intended --- src/common/factory.hpp | 155 +++++++++++++++--------- src/tool/try.cpp | 9 +- tests/components/common/factorytest.cpp | 7 +- 3 files changed, 105 insertions(+), 66 deletions(-) diff --git a/src/common/factory.hpp b/src/common/factory.hpp index bb2a28fee..2c24d697b 100644 --- a/src/common/factory.hpp +++ b/src/common/factory.hpp @@ -30,51 +30,10 @@ namespace cinelerra { - - namespace factory{ class VanillaAllocator; }//////////////////////////////////TODO - - /** - * Configurable template for creating Factory classes. - * These encapsulate the creating of new objects, indeed - * delegating the memory allocation to the backend layer. - * The clients get just a smart-pointer or similar handle - * to the created object, which will manage the ownership. - * - * The provided default implementation uses just std::auto_ptr, - * but delegates the allocation to cinelerra's backend-layer. - * - */ - template - < - class T, // the product to be created - template class SMP = std::auto_ptr,// smart-pointer actually returned - class ALO = factory::VanillaAllocator // Allocator facility to be used //////////////TODO - > - class Factory : protected ALO - { - public: - /** Object creating facility. - * Intended to be over/written/ with a variant taking - * the appropriate number of parameters and using the - * (privately inherited) functions of the allocator. - * Note: non-virtual. - */ - SMP operator() (){ return SMP (new T ); }; - - typedef SMP ptype; - - private: - void operator= (const Factory&); // copy prohibited - }; - - - - /* -- some example and default instantiiations -- */ - namespace factory { /** - * Example Allocator using just the normal C++ memory management. + * Example NOP Allocator using just the normal C++ memory management. * The intended use is for a Factory instance to iherit from this class. * Specialized Allocators typically overload operator new and delete. */ @@ -88,42 +47,124 @@ namespace cinelerra void* operator new (size_t siz) { return malloc (siz); }; void operator delete (void* p) { if (p) free (p); }; }; + + typedef VanillaAllocator DefaultALO; // Allocator facility to be used by default //////////////TODO + /** + * Wrapping any object created by the Factory into some smart ptr class. + * The Factory class inherits this functionallity, so it can be exchanged + * independently from the actual object creation behaviour. For example, + * an Factory implementing some elaborate subclass creation scheme could + * be intantiated to either procuce auto-ptrs or shared-ptrs. + */ + template + < class T, // the product to be created + class SMP =std::auto_ptr // smart-pointer actually returned + > + class Wrapper + { + protected: + SMP wrap (T* product) { return SMP (product); } + + public: + typedef SMP PType; + }; + + + /** + * Basic Factory Template, for definig flexible Factory classes. + * These encapsulate the logic for creating of new objects, maybe + * delegating the memory allocation to the backend layer. Usually, + * the clients get just a smart-pointer or similar handle to the + * created object, which will manage the ownership. + * + * The provided default implementation uses just std::auto_ptr, + * but delegates the allocation to cinelerra's backend-layer. + * + * @todo actually do the delgation of memory management instead of using VanillaAllocator! + */ + template + < class T, // the product to be created + class WR = Wrapper, // used for fabricating the wrapper + class ALO = DefaultALO // Allocator facility to be used + > + class Factory : public WR, protected ALO + { + public: + /** Object creating facility. + * Intended to be over/written/ with a variant taking + * the appropriate number of parameters and using the + * (privately inherited) functions of the allocator. + * Note: non-virtual. + */ + typename WR::PType operator() () { return wrap (new T ); } + + }; + + + + + /* -- some example and default instantiiations -- */ using std::tr1::shared_ptr; - /** a frequently used instantiation of the Factory, - * using the refcounting shared_ptr from Boost - * and for allocation just our default Allocator + /** + * a frequently used instantiation of the Wrapper, + * utilizingthe refcounting shared_ptr from Boost. */ template - class RefcountPtr : public Factory + class Wrapper > { - /** let the smart-Ptr use the custom operator delete, + /** let the smart-ptr use the custom operator delete, * which may be defined in our Allocator baseclass. */ static void destroy (T* victim) { delete victim; }; + protected: + shared_ptr wrap (T* product) { return shared_ptr (product, &destroy ); } public: - shared_ptr operator() () { return shared_ptr (new T, &destroy ); } + typedef shared_ptr PType; }; - - - /** another convienience instantiiation: auto_ptr-Factory, - * actually creating a subclass of the returned type + + + /** + * Shortcut: commonly used (partial) instantiation of the Factory, + * generating refcounting shared_ptr wrapped Objects. */ - template - class SubclassPtr : public Factory + template + < class T, // the product to be created + class ALO = DefaultALO // Allocator facility to be used + > + class RefcountPtr : public Factory >, ALO> { - typedef std::auto_ptr aP; - public: - aP operator() (){ return aP (new TImpl ); }; + typedef shared_ptr PType; + }; + + + /** + * another convienience instantiiation: auto_ptr-to-Impl-Factory. + * Creating an implementation subclass and wraps into auto_ptr. + */ + template + < class T, // Interface class + class TImpl, // Implementation class to be created + class ALO = DefaultALO // Allocator facility to be used + > + class PImplPtr : public Factory, ALO> + { + public: + typedef std::auto_ptr PType; + PType operator() (){ return wrap (new TImpl); }; }; } // namespace factory + /// @note Factory can be usable as-is (wraps into std::auto_ptr) + using factory::Factory; + + } // namespace cinelerra #endif diff --git a/src/tool/try.cpp b/src/tool/try.cpp index b948ada31..7d3a0783f 100644 --- a/src/tool/try.cpp +++ b/src/tool/try.cpp @@ -4,25 +4,22 @@ */ // 8/07 - how to control NOBUG?? +// execute with NOBUG_LOG='ttt:TRACE' bin/try #include -#define NOBUG_LOG_LIMIT LOG_ERR #include -NOBUG_DECLARE_FLAG(ttt); - -NOBUG_DEFINE_FLAG(ttt); +//NOBUG_CPP_DEFINE_FLAG(ttt); +NOBUG_CPP_DEFINE_FLAG_LIMIT(ttt, LOG_WARNING); int main (int argc, char* argv[]) { NOBUG_INIT; - NOBUG_INIT_FLAG_LIMIT(ttt, LOG_WARNING); - TRACE(ttt,"trace"); INFO(ttt,"info"); NOTICE(ttt,"notice"); diff --git a/tests/components/common/factorytest.cpp b/tests/components/common/factorytest.cpp index b3038faf4..8358ed2a3 100644 --- a/tests/components/common/factorytest.cpp +++ b/tests/components/common/factorytest.cpp @@ -68,6 +68,8 @@ namespace cinelerra } + /// @todo: make it possible to have a private destructor + public: ~TargetObj() throw() { delete heapData_; @@ -107,7 +109,6 @@ namespace cinelerra */ class ObjFactory : public factory::RefcountPtr { - static void destroy (TargetObj* victim) { delete victim; }; public: /** specialized Factory method for creating TargetObj instances. * Here, we invoke a special constructor, but basically we could @@ -115,14 +116,14 @@ namespace cinelerra * registering objects etc. Further, we could have used a * custom allocator or a special deleter function. */ - ptype operator() (uint param){ return ptype (new TargetObj (param), &destroy); }; + PType operator() (uint param) { return wrap (new TargetObj(param) ); } }; /** shorthand for the created smart-pointer class, * here it's a (refcounting) boost::shared_ptr */ - typedef ObjFactory::ptype pTarget; + typedef ObjFactory::PType pTarget; ObjFactory TargetObj::create;