diff --git a/include/boost/function.hpp b/include/boost/function.hpp index 01e3fb3..205878a 100644 --- a/include/boost/function.hpp +++ b/include/boost/function.hpp @@ -1,6 +1,6 @@ // Boost.Function library -// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu) +// Copyright (C) 2001-2002 Doug Gregor (gregod@cs.rpi.edu) // // Permission to copy, use, sell and distribute this software is granted // provided this copyright notice appears in all copies. @@ -53,13 +53,12 @@ namespace boost { typename T8, typename T9, typename T10, - typename Policy, - typename Mixin, + typename ThreadingPolicy, typename Allocator > struct params { - typedef function0 type; + typedef function0 type; }; }; @@ -78,13 +77,12 @@ namespace boost { typename T8, typename T9, typename T10, - typename Policy, - typename Mixin, + typename ThreadingPolicy, typename Allocator > struct params { - typedef function1 type; + typedef function1 type; }; }; @@ -103,13 +101,12 @@ namespace boost { typename T8, typename T9, typename T10, - typename Policy, - typename Mixin, + typename ThreadingPolicy, typename Allocator > struct params { - typedef function2 type; + typedef function2 type; }; }; @@ -128,13 +125,12 @@ namespace boost { typename T8, typename T9, typename T10, - typename Policy, - typename Mixin, + typename ThreadingPolicy, typename Allocator > struct params { - typedef function3 type; + typedef function3 type; }; }; @@ -153,13 +149,12 @@ namespace boost { typename T8, typename T9, typename T10, - typename Policy, - typename Mixin, + typename ThreadingPolicy, typename Allocator > struct params { - typedef function4 type; + typedef function4 type; }; }; @@ -178,13 +173,12 @@ namespace boost { typename T8, typename T9, typename T10, - typename Policy, - typename Mixin, + typename ThreadingPolicy, typename Allocator > struct params { - typedef function5 + typedef function5 type; }; }; @@ -204,13 +198,12 @@ namespace boost { typename T8, typename T9, typename T10, - typename Policy, - typename Mixin, + typename ThreadingPolicy, typename Allocator > struct params { - typedef function6 + typedef function6 type; }; }; @@ -230,13 +223,12 @@ namespace boost { typename T8, typename T9, typename T10, - typename Policy, - typename Mixin, + typename ThreadingPolicy, typename Allocator > struct params { - typedef function7 type; }; }; @@ -256,13 +248,12 @@ namespace boost { typename T8, typename T9, typename T10, - typename Policy, - typename Mixin, + typename ThreadingPolicy, typename Allocator > struct params { - typedef function8 type; }; }; @@ -282,14 +273,13 @@ namespace boost { typename T8, typename T9, typename T10, - typename Policy, - typename Mixin, + typename ThreadingPolicy, typename Allocator > struct params { - typedef function9 type; + typedef function9 type; }; }; @@ -308,14 +298,13 @@ namespace boost { typename T8, typename T9, typename T10, - typename Policy, - typename Mixin, + typename ThreadingPolicy, typename Allocator > struct params { typedef function10 type; + ThreadingPolicy, Allocator> type; }; }; @@ -331,16 +320,15 @@ namespace boost { typename T8, typename T9, typename T10, - typename Policy = empty_function_policy, - typename Mixin = empty_function_mixin, - typename Allocator = std::allocator + typename ThreadingPolicy = BOOST_FUNCTION_DEFAULT_THREADING_POLICY, + typename Allocator = BOOST_FUNCTION_DEFAULT_ALLOCATOR > struct get_function_impl { typedef typename real_get_function_impl< (count_used_args::value) >::template params::type + ThreadingPolicy, Allocator>::type type; }; @@ -356,55 +344,37 @@ namespace boost { typename T8, typename T9, typename T10, - typename MyPolicy = empty_function_policy, - typename MyMixin = empty_function_mixin, - typename MyAllocator = std::allocator + typename MyThreadingPolicy = BOOST_FUNCTION_DEFAULT_THREADING_POLICY, + typename MyAllocator = BOOST_FUNCTION_DEFAULT_ALLOCATOR > struct function_traits_builder { typedef typename get_function_impl::type type; - typedef MyPolicy policy_type; - typedef MyMixin mixin_type; + typedef MyThreadingPolicy threading_policy_type; typedef MyAllocator allocator_type; #ifndef BOOST_NO_DEPENDENT_NESTED_DERIVATIONS - template - struct policy : + template + struct threading_policy : public function_traits_builder {}; - - template - struct mixin : - public function_traits_builder {}; template struct allocator : public function_traits_builder {}; #else - template - struct policy + template + struct threading_policy { typedef typename function_traits_builder::type - type; - }; - - template - struct mixin - { - typedef typename function_traits_builder::type type; }; @@ -413,8 +383,9 @@ namespace boost { struct allocator { typedef typename function_traits_builder::type + T8, T9, T10, + threading_policy_type, + Allocator>::type type; }; #endif @@ -448,8 +419,7 @@ namespace boost { base_type; public: - typedef typename base_type::policy_type policy_type; - typedef typename base_type::mixin_type mixin_type; + typedef typename base_type::threading_policy_type policy_type; typedef typename base_type::allocator_type allocator_type; typedef function self_type; @@ -463,37 +433,21 @@ namespace boost { template self_type& operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) { - self_type(f).swap(*this); + base_type::operator=(f); return *this; } self_type& operator=(const base_type& f) { - self_type(f).swap(*this); + base_type::operator=(f); return *this; } self_type& operator=(const self_type& f) { - self_type(f).swap(*this); + base_type::operator=(static_cast(f)); return *this; } - - template - void set(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) - { - self_type(f).swap(*this); - } - - void set(const base_type& f) - { - self_type(f).swap(*this); - } - - void set(const self_type& f) - { - self_type(f).swap(*this); - } }; template #include #include +#include +#include #if defined(BOOST_MSVC) && BOOST_MSVC <= 1300 || defined(__ICL) && __ICL <= 600 || defined(__MWERKS__) && __MWERKS__ < 0x2406 # define BOOST_FUNCTION_TARGET_FIX(x) x @@ -31,54 +33,22 @@ # define BOOST_FUNCTION_TARGET_FIX(x) #endif // not MSVC +#ifndef BOOST_FUNCTION_DEFAULT_THREADING_POLICY +# define BOOST_FUNCTION_DEFAULT_THREADING_POLICY single_threaded +#endif + +// Type of the default allocator +#ifndef BOOST_NO_STD_ALLOCATOR +# define BOOST_FUNCTION_DEFAULT_ALLOCATOR std::allocator +#else +# define BOOST_FUNCTION_DEFAULT_ALLOCATOR int +#endif // BOOST_NO_STD_ALLOCATOR + namespace boost { namespace detail { namespace function { template struct truth {}; - /* - * The ct_if implementation is temporary code. When a Boost metaprogramming - * library is introduced, Boost.Function will use it instead. - */ - namespace intimate { - struct SelectThen - { - template - struct Result - { - typedef Then type; - }; - }; - - struct SelectElse - { - template - struct Result - { - typedef Else type; - }; - }; - - template - struct Selector - { - typedef SelectThen type; - }; - - template<> - struct Selector - { - typedef SelectElse type; - }; - } // end namespace intimate - - template - struct ct_if - { - typedef typename intimate::Selector::type select; - typedef typename select::template Result::type type; - }; - /** * A union of a function pointer and a void pointer. This is necessary * because 5.2.10/6 allows reinterpret_cast<> to safely cast between @@ -158,7 +128,7 @@ namespace boost { // The trivial manager does nothing but return the same pointer (if we // are cloning) or return the null pointer (if we are deleting). inline any_pointer trivial_manager(any_pointer f, - functor_manager_operation_type op) + functor_manager_operation_type op) { if (op == clone_functor_tag) return f; @@ -179,7 +149,7 @@ namespace boost { // For function pointers, the manager is trivial static inline any_pointer manager(any_pointer function_ptr, - functor_manager_operation_type op, + functor_manager_operation_type op, function_ptr_tag) { if (op == clone_functor_tag) @@ -307,13 +277,13 @@ namespace boost { public: // should be protected, but GCC 2.95.3 will fail to allow access detail::function::any_pointer (*manager)( detail::function::any_pointer, + detail::function::functor_manager_operation_type); + detail::function::any_pointer functor; + #if (defined __SUNPRO_CC) && (__SUNPRO_CC <= 0x530) && !(defined BOOST_NO_COMPILER_CONFIG) // Sun C++ 5.3 can't handle the safe_bool idiom, so don't use it operator bool () const { return !this->empty(); } #else - detail::function::functor_manager_operation_type); - detail::function::any_pointer functor; - private: struct dummy { void nonnull() {}; @@ -346,7 +316,7 @@ namespace boost { template inline bool has_empty_target(const FunctionObj&, truth) { - return false; + return false; } // The result is a Boost.Function object, so query whether it is empty @@ -356,29 +326,20 @@ namespace boost { { return f.empty(); } + + template + struct scoped_double_lock + { + scoped_double_lock(const Mixin& m1, const Mixin& m2) : + lock1(&m1 < &m2? m1 : m2), lock2(!(&m1 < &m2)? m1 : m2) + { + } + + Lock lock1; + Lock lock2; + }; } // end namespace function } // end namespace detail - - // The default function policy is to do nothing before and after the call. - struct empty_function_policy - { - inline void precall(const function_base*) {} - inline void postcall(const function_base*) {} - }; - - // The default function mixin does nothing. The assignment and - // copy-construction operators are all defined because MSVC defines broken - // versions. - struct empty_function_mixin - { - empty_function_mixin() {} - empty_function_mixin(const empty_function_mixin&) {} - - empty_function_mixin& operator=(const empty_function_mixin&) - { - return *this; - } - }; } #endif // BOOST_FUNCTION_BASE_HEADER diff --git a/include/boost/function/function_template.hpp b/include/boost/function/function_template.hpp index ab0d18e..29eda6c 100644 --- a/include/boost/function/function_template.hpp +++ b/include/boost/function/function_template.hpp @@ -1,6 +1,6 @@ // Boost.Function library -// Copyright (C) 2001 Doug Gregor (gregod@cs.rpi.edu) +// Copyright (C) 2001-2002 Doug Gregor (gregod@cs.rpi.edu) // // Permission to copy, use, sell and distribute this software is granted // provided this copyright notice appears in all copies. @@ -25,13 +25,6 @@ # include #endif // BOOST_FUNCTION_FUNCTION_TEMPLATE_HPP -// Type of the default allocator -#ifndef BOOST_NO_STD_ALLOCATOR -# define BOOST_FUNCTION_DEFAULT_ALLOCATOR std::allocator -#else -# define BOOST_FUNCTION_DEFAULT_ALLOCATOR int -#endif // BOOST_NO_STD_ALLOCATOR - // Comma if nonzero number of arguments #if BOOST_FUNCTION_NUM_ARGS == 0 # define BOOST_FUNCTION_COMMA @@ -229,15 +222,18 @@ namespace boost { template< typename R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_PARMS, - typename Policy = empty_function_policy, - typename Mixin = empty_function_mixin, + typename ThreadingPolicy = BOOST_FUNCTION_DEFAULT_THREADING_POLICY, typename Allocator = BOOST_FUNCTION_DEFAULT_ALLOCATOR > - class BOOST_FUNCTION_FUNCTION : public function_base, public Mixin + class BOOST_FUNCTION_FUNCTION : public function_base, + public ThreadingPolicy::mixin { typedef typename detail::function::function_return_type::type internal_result_type; + typedef typename ThreadingPolicy::mixin threading_mixin; + typedef typename ThreadingPolicy::lock lock; + public: BOOST_STATIC_CONSTANT(int, args = BOOST_FUNCTION_NUM_ARGS); @@ -253,54 +249,48 @@ namespace boost { #else typedef internal_result_type result_type; #endif // BOOST_NO_VOID_RETURNS - typedef Policy policy_type; - typedef Mixin mixin_type; typedef Allocator allocator_type; typedef BOOST_FUNCTION_FUNCTION self_type; + typedef ThreadingPolicy threading_policy_type; - BOOST_FUNCTION_FUNCTION() : function_base(), Mixin(), invoker(0) {} - - explicit BOOST_FUNCTION_FUNCTION(const Mixin& m) : - function_base(), Mixin(m), invoker(0) - { - } + BOOST_FUNCTION_FUNCTION() : function_base(), invoker(0) {} // MSVC chokes if the following two constructors are collapsed into // one with a default parameter. template BOOST_FUNCTION_FUNCTION(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) : - function_base(), Mixin(), invoker(0) - { - this->assign_to(f); - } - - template - BOOST_FUNCTION_FUNCTION(Functor f, const Mixin& m) : - function_base(), Mixin(m), invoker(0) + function_base(), invoker(0) { this->assign_to(f); } BOOST_FUNCTION_FUNCTION(const BOOST_FUNCTION_FUNCTION& f) : - function_base(), Mixin(static_cast(f)), invoker(0) + function_base(), invoker(0) { + // Lock the other function object so it can't change during assignment + lock l(static_cast(f)); + (void)l; this->assign_to_own(f); } - ~BOOST_FUNCTION_FUNCTION() { clear(); } + ~BOOST_FUNCTION_FUNCTION() + { + lock l(static_cast(*this)); + (void)l; + clear(); + } result_type operator()(BOOST_FUNCTION_PARMS) const { + // Make sure this function can't change while it is being invoked + lock l(static_cast(*this)); + (void)l; assert(!this->empty()); - policy_type policy; - policy.precall(this); - internal_result_type result = invoker(function_base::functor BOOST_FUNCTION_COMMA BOOST_FUNCTION_ARGS); - policy.postcall(this); #ifndef BOOST_NO_VOID_RETURNS return static_cast(result); #else @@ -317,49 +307,45 @@ namespace boost { BOOST_FUNCTION_FUNCTION& operator=(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) { - self_type(f, static_cast(*this)).swap(*this); + self_type other(f); + lock l(static_cast(*this)); + (void)l; + other.unlocked_swap(*this); return *this; } - template - void set(Functor BOOST_FUNCTION_TARGET_FIX(const &) f) - { - self_type(f, static_cast(*this)).swap(*this); - } - // Assignment from another BOOST_FUNCTION_FUNCTION BOOST_FUNCTION_FUNCTION& operator=(const BOOST_FUNCTION_FUNCTION& f) { if (&f == this) return *this; - self_type(f).swap(*this); + self_type other(f); + lock l(static_cast(*this)); + (void)l; + other.unlocked_swap(*this); + return *this; } - // Assignment from another BOOST_FUNCTION_FUNCTION - void set(const BOOST_FUNCTION_FUNCTION& f) - { - if (&f == this) - return; - - self_type(f).swap(*this); - } - void swap(BOOST_FUNCTION_FUNCTION& other) { if (&other == this) return; - std::swap(function_base::manager, other.manager); - std::swap(function_base::functor, other.functor); - std::swap(invoker, other.invoker); - std::swap(static_cast(*this), static_cast(other)); + detail::function::scoped_double_lock l(*this, + other); + (void)l; + + unlocked_swap(other); } // Clear out a target, if there is one void clear() { + lock l(static_cast(*this)); + (void)l; + if (function_base::manager) { function_base::functor = function_base::manager(function_base::functor, @@ -378,7 +364,7 @@ namespace boost { function_base::manager = f.manager; function_base::functor = f.manager(f.functor, detail::function::clone_functor_tag); - } + } } template @@ -502,6 +488,13 @@ namespace boost { function_base::functor = detail::function::any_pointer(this); } + void unlocked_swap(BOOST_FUNCTION_FUNCTION& other) + { + std::swap(function_base::manager, other.manager); + std::swap(function_base::functor, other.functor); + std::swap(invoker, other.invoker); + } + typedef internal_result_type (*invoker_type)(detail::function::any_pointer BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS); @@ -510,19 +503,17 @@ namespace boost { }; template + typename ThreadingPolicy, typename Allocator> inline void swap(BOOST_FUNCTION_FUNCTION< R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS , - Policy, - Mixin, + ThreadingPolicy, Allocator >& f1, BOOST_FUNCTION_FUNCTION< R BOOST_FUNCTION_COMMA BOOST_FUNCTION_TEMPLATE_ARGS, - Policy, - Mixin, + ThreadingPolicy, Allocator >& f2) { @@ -531,7 +522,6 @@ namespace boost { } // Cleanup after ourselves... -#undef BOOST_FUNCTION_DEFAULT_ALLOCATOR #undef BOOST_FUNCTION_COMMA #undef BOOST_FUNCTION_FUNCTION #undef BOOST_FUNCTION_FUNCTION_INVOKER