From b11ac46b76357f837efb426abe62fe41dbab4fbe Mon Sep 17 00:00:00 2001 From: Ichthyostega Date: Fri, 31 Aug 2007 16:25:04 +0200 Subject: [PATCH] added possibility to pass a custom deleter function down to shared_ptr. Note: actually all of this seems against the spirit of C++ (and OO in general). This is a do-it-yourself aproach which adds far to much complexity (accidental, not fundamental complexity). So I checked it in for the record, but will abandon this aproach and rely on overloading of operator new / delete if necessary (and when we really need it) --- src/common/factory.hpp | 38 ++++++++++++++++++++----- tests/components/common/factorytest.cpp | 10 +++++-- 2 files changed, 39 insertions(+), 9 deletions(-) diff --git a/src/common/factory.hpp b/src/common/factory.hpp index 2c24d697b..1adc44e69 100644 --- a/src/common/factory.hpp +++ b/src/common/factory.hpp @@ -65,9 +65,13 @@ namespace cinelerra { protected: SMP wrap (T* product) { return SMP (product); } + public: typedef SMP PType; + + typedef void (*DelHandler) (T* victim); ///< custom deleter function + void setDelHandler (DelHandler) {}; ///< if non-standard deleting is necessary }; @@ -99,6 +103,12 @@ namespace cinelerra */ typename WR::PType operator() () { return wrap (new T ); } + protected: + /** this custom deleter function can be used if the + * operator delete call needs to be in the current scope. + * @see RefcountPtr + */ + static void destroy (T* victim) { delete victim; }; }; @@ -110,26 +120,34 @@ namespace cinelerra /** * a frequently used instantiation of the Wrapper, - * utilizingthe refcounting shared_ptr from Boost. + * utilizing the refcounting shared_ptr from Boost. */ template class Wrapper > { - /** 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 ); } + shared_ptr wrap (T* product) { return shared_ptr (product, destroy_ ); } + public: typedef shared_ptr PType; + + + Wrapper () : destroy_(&stdDelete) { } + + typedef void (*DelHandler) (T* victim); ///< custom deleter function + void setDelHandler (DelHandler d) { this->destroy_ = d; } ///< custom deleter used by shard_ptr + + private: + DelHandler destroy_; + static void stdDelete (T* victim) { delete victim; }; ///< by default just delete objects normally }; /** * Shortcut: commonly used (partial) instantiation of the Factory, - * generating refcounting shared_ptr wrapped Objects. + * generating refcounting shared_ptr wrapped Objects. Built upon + * the corresponding special intstantiation of the Wrapper template. */ template < class T, // the product to be created @@ -139,6 +157,12 @@ namespace cinelerra { public: typedef shared_ptr PType; + + /** especially the shared_ptr will use Factory::destroy, + * so it is sufficient to make Factory a friend if the + * Target class to be produced has private ctor/dtors + */ + RefcountPtr() { setDelHandler(&this->destroy); } }; diff --git a/tests/components/common/factorytest.cpp b/tests/components/common/factorytest.cpp index 8358ed2a3..877c9ff8e 100644 --- a/tests/components/common/factorytest.cpp +++ b/tests/components/common/factorytest.cpp @@ -68,8 +68,6 @@ namespace cinelerra } - /// @todo: make it possible to have a private destructor - public: ~TargetObj() throw() { delete heapData_; @@ -117,6 +115,14 @@ namespace cinelerra * custom allocator or a special deleter function. */ PType operator() (uint param) { return wrap (new TargetObj(param) ); } + + ObjFactory () { setDelHandler(&destroy); } + + protected: + /** define a custom deleter function, so the actual destrucor call + * happenes within the scope of ObjFactory, which is friend of TargetObj + */ + static void destroy (TargetObj* victim) { delete victim; }; };