From 3f13d39604747a4f796290372cb50f50a1a7d2a6 Mon Sep 17 00:00:00 2001 From: Douglas Gregor Date: Mon, 19 Nov 2001 14:52:04 +0000 Subject: [PATCH] function_base.hpp: function_template.hpp: - Removed implementation based on virtual functions. Such an implementation can't meet exception safety requirements made by the manager/invoker version. [SVN r11726] --- include/boost/function/function_base.hpp | 13 - include/boost/function/function_template.hpp | 365 +------------------ 2 files changed, 10 insertions(+), 368 deletions(-) diff --git a/include/boost/function/function_base.hpp b/include/boost/function/function_base.hpp index 9a76da7..b1a48ce 100644 --- a/include/boost/function/function_base.hpp +++ b/include/boost/function/function_base.hpp @@ -138,7 +138,6 @@ namespace boost { ptr_or_obj_tag>::type type; }; -#ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS /** * The functor_manager class contains a static function "manage" which * can clone or destroy the given function/function object pointer. @@ -232,7 +231,6 @@ namespace boost { return manager(functor_ptr, op, tag_type()); } }; -#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS // value=1 if the given type is not "unusable" template @@ -278,16 +276,6 @@ namespace boost { */ class function_base { -#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS - public: - function_base() : impl(0) {} - - bool empty() const { return impl == 0; } - - - protected: - void* impl; // Derived class is responsible for knowing the real type -#else public: function_base() : manager(0), functor(static_cast(0)) {} @@ -299,7 +287,6 @@ namespace boost { detail::function::any_pointer, detail::function::functor_manager_operation_type); detail::function::any_pointer functor; -#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS private: struct dummy { diff --git a/include/boost/function/function_template.hpp b/include/boost/function/function_template.hpp index 14f050e..bdad19e 100644 --- a/include/boost/function/function_template.hpp +++ b/include/boost/function/function_template.hpp @@ -13,21 +13,12 @@ // For more information, see http://www.boost.org -/* Note: this header is a header template and must NOT have multiple-inclusion - protection. */ +// Note: this header is a header template and must NOT have multiple-inclusion +// protection. #include #include -// Zero-initialize the "invoker" member of the functionN object. -// The invoker member only exists when we aren't using the virtual -// function implementation -#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS -# define BOOST_FUNCTION_INIT -#else -# define BOOST_FUNCTION_INIT , invoker(0) -#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS - // Type of the default allocator #ifndef BOOST_NO_STD_ALLOCATOR # define BOOST_FUNCTION_DEFAULT_ALLOCATOR std::allocator @@ -38,161 +29,28 @@ namespace boost { namespace detail { namespace function { -#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS - template - struct BOOST_FUNCTION_INVOKER_BASE - { - virtual ~BOOST_FUNCTION_INVOKER_BASE() {} - virtual R call(BOOST_FUNCTION_PARMS) const = 0; - virtual BOOST_FUNCTION_INVOKER_BASE* clone() const = 0; - virtual void destroy(BOOST_FUNCTION_INVOKER_BASE*) = 0; - }; -#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS - template< typename FunctionPtr, -#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS - typename Allocator, -#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS > struct BOOST_FUNCTION_FUNCTION_INVOKER -#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS - : public BOOST_FUNCTION_INVOKER_BASE< - R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS - > -#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS { -#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS - explicit BOOST_FUNCTION_FUNCTION_INVOKER(FunctionPtr f) : - function_ptr(f) {} - - virtual R call(BOOST_FUNCTION_PARMS) const - { - return function_ptr(BOOST_FUNCTION_ARGS); - } - - virtual BOOST_FUNCTION_FUNCTION_INVOKER* clone() const - { -# ifdef BOOST_NO_STD_ALLOCATOR - return new BOOST_FUNCTION_FUNCTION_INVOKER(function_ptr); -# else - typedef typename Allocator:: - template rebind::other - allocator_type; - typedef typename allocator_type::pointer pointer_type; - allocator_type allocator; - - pointer_type copy = allocator.allocate(1); - allocator.construct(copy, *this); - return static_cast(copy); -# endif // BOOST_NO_STD_ALLOCATOR - } - - virtual void destroy(BOOST_FUNCTION_INVOKER_BASE< - R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS - >* p) - { -# ifdef BOOST_NO_STD_ALLOCATOR - delete p; -# else - BOOST_FUNCTION_FUNCTION_INVOKER* victim = - dynamic_cast(p); - - typedef typename Allocator:: - template rebind::other - allocator_type; - typedef typename allocator_type::pointer pointer_type; - allocator_type allocator; - - allocator.destroy(victim); - allocator.deallocate(victim, 1); -# endif // BOOST_NO_STD_ALLOCATOR - } - - private: - mutable FunctionPtr function_ptr; -#else static R invoke(any_pointer function_ptr BOOST_FUNCTION_COMMA BOOST_FUNCTION_PARMS) { FunctionPtr f = reinterpret_cast(function_ptr.func_ptr); return f(BOOST_FUNCTION_ARGS); } -#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS }; template< typename FunctionPtr, -# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS - typename Allocator, -# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS > struct BOOST_FUNCTION_VOID_FUNCTION_INVOKER -# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS - : public BOOST_FUNCTION_INVOKER_BASE< - unusable BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS - > -# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS { -# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS - explicit BOOST_FUNCTION_VOID_FUNCTION_INVOKER(FunctionPtr f) : - function_ptr(f) {} - - virtual unusable call(BOOST_FUNCTION_PARMS) const - { - function_ptr(BOOST_FUNCTION_ARGS); - return unusable(); - } - - virtual BOOST_FUNCTION_VOID_FUNCTION_INVOKER* clone() const - { -# ifdef BOOST_NO_STD_ALLOCATOR - return new BOOST_FUNCTION_VOID_FUNCTION_INVOKER(function_ptr); -# else - typedef typename Allocator:: - template rebind::other - allocator_type; - typedef typename allocator_type::pointer pointer_type; - allocator_type allocator; - - pointer_type copy = allocator.allocate(1); - allocator.construct(copy, *this); - return static_cast(copy); -# endif // BOOST_NO_STD_ALLOCATOR - } - - virtual void destroy(BOOST_FUNCTION_INVOKER_BASE< - unusable BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS - >* p) - { -# ifdef BOOST_NO_STD_ALLOCATOR - delete p; -# else - BOOST_FUNCTION_VOID_FUNCTION_INVOKER* victim = - dynamic_cast(p); - - typedef typename Allocator:: - template rebind::other - allocator_type; - typedef typename allocator_type::pointer pointer_type; - allocator_type allocator; - - allocator.destroy(victim); - allocator.deallocate(victim, 1); -# endif // BOOST_NO_STD_ALLOCATOR - } - - private: - mutable FunctionPtr function_ptr; -# else static unusable invoke(any_pointer function_ptr BOOST_FUNCTION_COMMA BOOST_FUNCTION_PARMS) @@ -201,76 +59,15 @@ namespace boost { f(BOOST_FUNCTION_ARGS); return unusable(); } -# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS }; template< typename FunctionObj, -#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS - typename Allocator, -#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS > struct BOOST_FUNCTION_FUNCTION_OBJ_INVOKER -#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS - : public BOOST_FUNCTION_INVOKER_BASE< - R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS - > -#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS { -#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS - explicit BOOST_FUNCTION_FUNCTION_OBJ_INVOKER(const FunctionObj& f) : - function_obj(f) {} - - virtual R call(BOOST_FUNCTION_PARMS) const - { - return function_obj(BOOST_FUNCTION_ARGS); - } - - virtual BOOST_FUNCTION_FUNCTION_OBJ_INVOKER* clone() const - { -#ifdef BOOST_NO_STD_ALLOCATOR - return new BOOST_FUNCTION_FUNCTION_OBJ_INVOKER(function_obj); -#else - typedef typename Allocator:: - template rebind::other - allocator_type; - typedef typename allocator_type::pointer pointer_type; - allocator_type allocator; - - pointer_type copy = allocator.allocate(1); - allocator.construct(copy, *this); - return static_cast(copy); -#endif // BOOST_NO_STD_ALLOCATOR - } - - virtual void destroy(BOOST_FUNCTION_INVOKER_BASE< - R BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS - >* p) - { -#ifdef BOOST_NO_STD_ALLOCATOR - delete p; -#else - BOOST_FUNCTION_FUNCTION_OBJ_INVOKER* victim = - dynamic_cast(p); - - typedef typename Allocator:: - template rebind::other - allocator_type; - typedef typename allocator_type::pointer pointer_type; - allocator_type allocator; - - allocator.destroy(victim); - allocator.deallocate(victim, 1); -#endif // BOOST_NO_STD_ALLOCATOR - } - - private: - mutable FunctionObj function_obj; -#else static R invoke(any_pointer function_obj_ptr BOOST_FUNCTION_COMMA BOOST_FUNCTION_PARMS) @@ -278,77 +75,15 @@ namespace boost { FunctionObj* f = static_cast(function_obj_ptr.obj_ptr); return (*f)(BOOST_FUNCTION_ARGS); } -#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS }; template< typename FunctionObj, -# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS - typename Allocator, -# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS > struct BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER -# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS - : public BOOST_FUNCTION_INVOKER_BASE< - unusable BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS - > -# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS { -# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS - explicit BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER(const FunctionObj& f) - : function_obj(f) {} - - virtual unusable call(BOOST_FUNCTION_PARMS) const - { - function_obj(BOOST_FUNCTION_ARGS); - return unusable(); - } - - virtual BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER* clone() const - { -# ifdef BOOST_NO_STD_ALLOCATOR - return new BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER(function_obj); -# else - typedef typename Allocator:: - template rebind::other - allocator_type; - typedef typename allocator_type::pointer pointer_type; - allocator_type allocator; - - pointer_type copy = allocator.allocate(1); - allocator.construct(copy, *this); - return static_cast(copy); -# endif // BOOST_NO_STD_ALLOCATOR - } - - virtual void destroy(BOOST_FUNCTION_INVOKER_BASE< - unusable BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS - >* p) - { -# ifdef BOOST_NO_STD_ALLOCATOR - delete p; -# else - BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER* victim = - dynamic_cast(p); - - typedef typename Allocator:: - template rebind::other - allocator_type; - typedef typename allocator_type::pointer pointer_type; - allocator_type allocator; - - allocator.destroy(victim); - allocator.deallocate(victim, 1); -# endif // BOOST_NO_STD_ALLOCATOR - } - - private: - mutable FunctionObj function_obj; -# else static unusable invoke(any_pointer function_obj_ptr BOOST_FUNCTION_COMMA BOOST_FUNCTION_PARMS) @@ -358,7 +93,6 @@ namespace boost { (*f)(BOOST_FUNCTION_ARGS); return unusable(); } -# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS }; template< @@ -372,17 +106,11 @@ namespace boost { typedef typename IF<(is_void::value), BOOST_FUNCTION_VOID_FUNCTION_INVOKER< FunctionPtr, -#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS - Allocator, -#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS >, BOOST_FUNCTION_FUNCTION_INVOKER< FunctionPtr, -#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS - Allocator, -#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS > @@ -400,17 +128,11 @@ namespace boost { typedef typename IF<(is_void::value), BOOST_FUNCTION_VOID_FUNCTION_OBJ_INVOKER< FunctionObj, -#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS - Allocator, -#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS >, BOOST_FUNCTION_FUNCTION_OBJ_INVOKER< FunctionObj, -#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS - Allocator, -#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS > @@ -444,20 +166,10 @@ namespace boost { typedef Allocator allocator_type; typedef BOOST_FUNCTION_FUNCTION self_type; - private: -#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS - typedef detail::function::BOOST_FUNCTION_INVOKER_BASE< - result_type BOOST_FUNCTION_COMMA - BOOST_FUNCTION_TEMPLATE_ARGS - > - impl_type; -#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS - - public: - BOOST_FUNCTION_FUNCTION() : function_base(), Mixin() BOOST_FUNCTION_INIT {} + BOOST_FUNCTION_FUNCTION() : function_base(), Mixin(), invoker(0) {} explicit BOOST_FUNCTION_FUNCTION(const Mixin& m) : - function_base(), Mixin(m) BOOST_FUNCTION_INIT + function_base(), Mixin(m), invoker(0) { } @@ -465,14 +177,14 @@ namespace boost { // one with a default parameter. template BOOST_FUNCTION_FUNCTION(const Functor& f) : - function_base(), Mixin() BOOST_FUNCTION_INIT + function_base(), Mixin(), invoker(0) { this->assign_to(f); } template BOOST_FUNCTION_FUNCTION(const Functor& f, const Mixin& m) : - function_base(), Mixin(m) BOOST_FUNCTION_INIT + function_base(), Mixin(m), invoker(0) { this->assign_to(f); } @@ -480,15 +192,14 @@ namespace boost { #ifdef __BORLANDC__ template BOOST_FUNCTION_FUNCTION(Functor* f, const Mixin& m = Mixin()) : - function_base(), Mixin(m) BOOST_FUNCTION_INIT + function_base(), Mixin(m), invoker(0) { this->assign_to(f); } #endif // __BORLANDC__ BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) : - function_base(), Mixin(static_cast(f)) - BOOST_FUNCTION_INIT + function_base(), Mixin(static_cast(f)), invoker(0) { this->assign_to_own(f); } @@ -502,13 +213,8 @@ namespace boost { policy_type policy; policy.precall(this); -#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS - const impl_type* i = reinterpret_cast(impl); - result_type result = i->call(BOOST_FUNCTION_ARGS); -#else result_type result = invoker(functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS); -#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS policy.postcall(this); return result; @@ -573,46 +279,29 @@ namespace boost { if (&other == this) return; -#ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS std::swap(manager, other.manager); std::swap(functor, other.functor); std::swap(invoker, other.invoker); -#else - std::swap(impl, other.impl); -#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS - std::swap(static_cast(*this),static_cast(other)); + std::swap(static_cast(*this), static_cast(other)); } // Clear out a target, if there is one void clear() { -#ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS - if (impl) { - impl_type* i = reinterpret_cast(impl); - i->destroy(i); - impl = 0; - } -#else if (manager) functor = manager(functor, detail::function::destroy_functor); manager = 0; invoker = 0; -#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS } private: void assign_to_own(const BOOST_FUNCTION_FUNCTION& f) { if (!f.empty()) { -# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS - impl_type* other_impl = reinterpret_cast(f.impl); - impl = static_cast(other_impl->clone()); -# else invoker = f.invoker; manager = f.manager; functor = f.manager(f.functor, detail::function::clone_functor); -# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS } } @@ -643,21 +332,6 @@ namespace boost { >::type invoker_type; -# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS -# ifdef BOOST_NO_STD_ALLOCATOR - impl_type* i = new invoker_type(f); -# else - typedef typename Allocator::template rebind::other - allocator_type; - typedef typename allocator_type::pointer pointer_type; - allocator_type allocator; - - pointer_type copy = allocator.allocate(1); - new (copy) invoker_type(f); - impl_type* i = static_cast(copy); -# endif // BOOST_NO_STD_ALLOCATOR - impl = static_cast(i); -# else invoker = &invoker_type::invoke; manager = &detail::function::functor_manager::manage; @@ -665,7 +339,6 @@ namespace boost { reinterpret_cast(f) ), detail::function::clone_functor); -# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS } } @@ -682,38 +355,20 @@ namespace boost { >::type invoker_type; -# ifdef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS -# ifdef BOOST_NO_STD_ALLOCATOR - impl_type* i = new invoker_type(f); -# else - typedef typename Allocator::template rebind::other - allocator_type; - typedef typename allocator_type::pointer pointer_type; - allocator_type allocator; - - pointer_type copy = allocator.allocate(1); - new (copy) invoker_type(f); - impl_type* i = static_cast(copy); -# endif // BOOST_NO_STD_ALLOCATOR - impl = static_cast(i); -# else invoker = &invoker_type::invoke; manager = &detail::function::functor_manager::manage; functor = manager(detail::function::any_pointer(const_cast(&f)), detail::function::clone_functor); -# endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS } } -#ifndef BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS typedef result_type (*invoker_type)(detail::function::any_pointer BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS); invoker_type invoker; -#endif // BOOST_FUNCTION_USE_VIRTUAL_FUNCTIONS }; template