Changed implementation to avoid calculating the size of the raw data buffer manually. Trim trailing spaces.

This commit is contained in:
Andrey Semashev
2016-04-02 17:31:22 +03:00
parent bde64bf9eb
commit 54988e8e91
2 changed files with 142 additions and 144 deletions

View File

@ -65,7 +65,7 @@ namespace boost {
* object pointers, and a structure that resembles a bound * object pointers, and a structure that resembles a bound
* member function pointer. * member function pointer.
*/ */
union function_buffer union function_buffer_members
{ {
// For pointers to function objects // For pointers to function objects
typedef void* obj_ptr_t; typedef void* obj_ptr_t;
@ -99,17 +99,15 @@ namespace boost {
bool is_const_qualified; bool is_const_qualified;
bool is_volatile_qualified; bool is_volatile_qualified;
} obj_ref; } obj_ref;
};
enum { union function_buffer
size1 = sizeof(obj_ptr_t) > sizeof(type_t) ? sizeof(obj_ptr_t) : sizeof(type_t), {
size2 = size1 > sizeof(func_ptr_t) ? size1 : sizeof(func_ptr_t), // Type-specific union members
size3 = size2 > sizeof(bound_memfunc_ptr_t) ? size2 : sizeof(bound_memfunc_ptr_t), mutable function_buffer_members members;
size4 = size3 > sizeof(obj_ref_t) ? size3 : sizeof(obj_ref_t),
data_size = size4
};
// To relax aliasing constraints // To relax aliasing constraints
mutable char data[data_size]; mutable char data[sizeof(function_buffer_members)];
}; };
/** /**
@ -176,42 +174,42 @@ namespace boost {
struct reference_manager struct reference_manager
{ {
static inline void static inline void
manage(const function_buffer& in_buffer, function_buffer& out_buffer, manage(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op) functor_manager_operation_type op)
{ {
switch (op) { switch (op) {
case clone_functor_tag: case clone_functor_tag:
out_buffer.obj_ref = in_buffer.obj_ref; out_buffer.members.obj_ref = in_buffer.members.obj_ref;
return; return;
case move_functor_tag: case move_functor_tag:
out_buffer.obj_ref = in_buffer.obj_ref; out_buffer.members.obj_ref = in_buffer.members.obj_ref;
in_buffer.obj_ref.obj_ptr = 0; in_buffer.members.obj_ref.obj_ptr = 0;
return; return;
case destroy_functor_tag: case destroy_functor_tag:
out_buffer.obj_ref.obj_ptr = 0; out_buffer.members.obj_ref.obj_ptr = 0;
return; return;
case check_functor_type_tag: case check_functor_type_tag:
{ {
// Check whether we have the same type. We can add // Check whether we have the same type. We can add
// cv-qualifiers, but we can't take them away. // cv-qualifiers, but we can't take them away.
if (*out_buffer.type.type == boost::typeindex::type_id<F>() if (*out_buffer.members.type.type == boost::typeindex::type_id<F>()
&& (!in_buffer.obj_ref.is_const_qualified && (!in_buffer.members.obj_ref.is_const_qualified
|| out_buffer.type.const_qualified) || out_buffer.members.type.const_qualified)
&& (!in_buffer.obj_ref.is_volatile_qualified && (!in_buffer.members.obj_ref.is_volatile_qualified
|| out_buffer.type.volatile_qualified)) || out_buffer.members.type.volatile_qualified))
out_buffer.obj_ptr = in_buffer.obj_ref.obj_ptr; out_buffer.members.obj_ptr = in_buffer.members.obj_ref.obj_ptr;
else else
out_buffer.obj_ptr = 0; out_buffer.members.obj_ptr = 0;
} }
return; return;
case get_functor_type_tag: case get_functor_type_tag:
out_buffer.type.type = &boost::typeindex::type_id<F>().type_info(); out_buffer.members.type.type = &boost::typeindex::type_id<F>().type_info();
out_buffer.type.const_qualified = in_buffer.obj_ref.is_const_qualified; out_buffer.members.type.const_qualified = in_buffer.members.obj_ref.is_const_qualified;
out_buffer.type.volatile_qualified = in_buffer.obj_ref.is_volatile_qualified; out_buffer.members.type.volatile_qualified = in_buffer.members.obj_ref.is_volatile_qualified;
return; return;
} }
} }
@ -225,9 +223,9 @@ namespace boost {
struct function_allows_small_object_optimization struct function_allows_small_object_optimization
{ {
BOOST_STATIC_CONSTANT BOOST_STATIC_CONSTANT
(bool, (bool,
value = ((sizeof(F) <= sizeof(function_buffer) && value = ((sizeof(F) <= sizeof(function_buffer) &&
(alignment_of<function_buffer>::value (alignment_of<function_buffer>::value
% alignment_of<F>::value == 0)))); % alignment_of<F>::value == 0))));
}; };
@ -239,7 +237,7 @@ namespace boost {
A(a) A(a)
{ {
} }
functor_wrapper(const functor_wrapper& f) : functor_wrapper(const functor_wrapper& f) :
F(static_cast<const F&>(f)), F(static_cast<const F&>(f)),
A(static_cast<const A&>(f)) A(static_cast<const A&>(f))
@ -258,35 +256,35 @@ namespace boost {
// Function pointers // Function pointers
static inline void static inline void
manage_ptr(const function_buffer& in_buffer, function_buffer& out_buffer, manage_ptr(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op) functor_manager_operation_type op)
{ {
if (op == clone_functor_tag) if (op == clone_functor_tag)
out_buffer.func_ptr = in_buffer.func_ptr; out_buffer.members.func_ptr = in_buffer.members.func_ptr;
else if (op == move_functor_tag) { else if (op == move_functor_tag) {
out_buffer.func_ptr = in_buffer.func_ptr; out_buffer.members.func_ptr = in_buffer.members.func_ptr;
in_buffer.func_ptr = 0; in_buffer.members.func_ptr = 0;
} else if (op == destroy_functor_tag) } else if (op == destroy_functor_tag)
out_buffer.func_ptr = 0; out_buffer.members.func_ptr = 0;
else if (op == check_functor_type_tag) { else if (op == check_functor_type_tag) {
if (*out_buffer.type.type == boost::typeindex::type_id<Functor>()) if (*out_buffer.members.type.type == boost::typeindex::type_id<Functor>())
out_buffer.obj_ptr = &in_buffer.func_ptr; out_buffer.members.obj_ptr = &in_buffer.members.func_ptr;
else else
out_buffer.obj_ptr = 0; out_buffer.members.obj_ptr = 0;
} else /* op == get_functor_type_tag */ { } else /* op == get_functor_type_tag */ {
out_buffer.type.type = &boost::typeindex::type_id<Functor>().type_info(); out_buffer.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
out_buffer.type.const_qualified = false; out_buffer.members.type.const_qualified = false;
out_buffer.type.volatile_qualified = false; out_buffer.members.type.volatile_qualified = false;
} }
} }
// Function objects that fit in the small-object buffer. // Function objects that fit in the small-object buffer.
static inline void static inline void
manage_small(const function_buffer& in_buffer, function_buffer& out_buffer, manage_small(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op) functor_manager_operation_type op)
{ {
if (op == clone_functor_tag || op == move_functor_tag) { if (op == clone_functor_tag || op == move_functor_tag) {
const functor_type* in_functor = const functor_type* in_functor =
reinterpret_cast<const functor_type*>(in_buffer.data); reinterpret_cast<const functor_type*>(in_buffer.data);
new (reinterpret_cast<void*>(out_buffer.data)) functor_type(*in_functor); new (reinterpret_cast<void*>(out_buffer.data)) functor_type(*in_functor);
@ -301,14 +299,14 @@ namespace boost {
(void)f; // suppress warning about the value of f not being used (MSVC) (void)f; // suppress warning about the value of f not being used (MSVC)
f->~Functor(); f->~Functor();
} else if (op == check_functor_type_tag) { } else if (op == check_functor_type_tag) {
if (*out_buffer.type.type == boost::typeindex::type_id<Functor>()) if (*out_buffer.members.type.type == boost::typeindex::type_id<Functor>())
out_buffer.obj_ptr = in_buffer.data; out_buffer.members.obj_ptr = in_buffer.data;
else else
out_buffer.obj_ptr = 0; out_buffer.members.obj_ptr = 0;
} else /* op == get_functor_type_tag */ { } else /* op == get_functor_type_tag */ {
out_buffer.type.type = &boost::typeindex::type_id<Functor>().type_info(); out_buffer.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
out_buffer.type.const_qualified = false; out_buffer.members.type.const_qualified = false;
out_buffer.type.volatile_qualified = false; out_buffer.members.type.volatile_qualified = false;
} }
} }
}; };
@ -321,7 +319,7 @@ namespace boost {
// Function pointers // Function pointers
static inline void static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer, manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, function_ptr_tag) functor_manager_operation_type op, function_ptr_tag)
{ {
functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op); functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
@ -329,15 +327,15 @@ namespace boost {
// Function objects that fit in the small-object buffer. // Function objects that fit in the small-object buffer.
static inline void static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer, manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, mpl::true_) functor_manager_operation_type op, mpl::true_)
{ {
functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op); functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
} }
// Function objects that require heap allocation // Function objects that require heap allocation
static inline void static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer, manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, mpl::false_) functor_manager_operation_type op, mpl::false_)
{ {
if (op == clone_functor_tag) { if (op == clone_functor_tag) {
@ -347,27 +345,27 @@ namespace boost {
// jewillco: Changing this to static_cast because GCC 2.95.3 is // jewillco: Changing this to static_cast because GCC 2.95.3 is
// obsolete. // obsolete.
const functor_type* f = const functor_type* f =
static_cast<const functor_type*>(in_buffer.obj_ptr); static_cast<const functor_type*>(in_buffer.members.obj_ptr);
functor_type* new_f = new functor_type(*f); functor_type* new_f = new functor_type(*f);
out_buffer.obj_ptr = new_f; out_buffer.members.obj_ptr = new_f;
} else if (op == move_functor_tag) { } else if (op == move_functor_tag) {
out_buffer.obj_ptr = in_buffer.obj_ptr; out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
in_buffer.obj_ptr = 0; in_buffer.members.obj_ptr = 0;
} else if (op == destroy_functor_tag) { } else if (op == destroy_functor_tag) {
/* Cast from the void pointer to the functor pointer type */ /* Cast from the void pointer to the functor pointer type */
functor_type* f = functor_type* f =
static_cast<functor_type*>(out_buffer.obj_ptr); static_cast<functor_type*>(out_buffer.members.obj_ptr);
delete f; delete f;
out_buffer.obj_ptr = 0; out_buffer.members.obj_ptr = 0;
} else if (op == check_functor_type_tag) { } else if (op == check_functor_type_tag) {
if (*out_buffer.type.type == boost::typeindex::type_id<Functor>()) if (*out_buffer.members.type.type == boost::typeindex::type_id<Functor>())
out_buffer.obj_ptr = in_buffer.obj_ptr; out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
else else
out_buffer.obj_ptr = 0; out_buffer.members.obj_ptr = 0;
} else /* op == get_functor_type_tag */ { } else /* op == get_functor_type_tag */ {
out_buffer.type.type = &boost::typeindex::type_id<Functor>().type_info(); out_buffer.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
out_buffer.type.const_qualified = false; out_buffer.members.type.const_qualified = false;
out_buffer.type.volatile_qualified = false; out_buffer.members.type.volatile_qualified = false;
} }
} }
@ -375,7 +373,7 @@ namespace boost {
// object can use the small-object optimization buffer or // object can use the small-object optimization buffer or
// whether we need to allocate it on the heap. // whether we need to allocate it on the heap.
static inline void static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer, manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, function_obj_tag) functor_manager_operation_type op, function_obj_tag)
{ {
manager(in_buffer, out_buffer, op, manager(in_buffer, out_buffer, op,
@ -384,7 +382,7 @@ namespace boost {
// For member pointers, we use the small-object optimization buffer. // For member pointers, we use the small-object optimization buffer.
static inline void static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer, manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, member_ptr_tag) functor_manager_operation_type op, member_ptr_tag)
{ {
manager(in_buffer, out_buffer, op, mpl::true_()); manager(in_buffer, out_buffer, op, mpl::true_());
@ -394,15 +392,15 @@ namespace boost {
/* Dispatch to an appropriate manager based on whether we have a /* Dispatch to an appropriate manager based on whether we have a
function pointer or a function object pointer. */ function pointer or a function object pointer. */
static inline void static inline void
manage(const function_buffer& in_buffer, function_buffer& out_buffer, manage(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op) functor_manager_operation_type op)
{ {
typedef typename get_function_tag<functor_type>::type tag_type; typedef typename get_function_tag<functor_type>::type tag_type;
switch (op) { switch (op) {
case get_functor_type_tag: case get_functor_type_tag:
out_buffer.type.type = &boost::typeindex::type_id<functor_type>().type_info(); out_buffer.members.type.type = &boost::typeindex::type_id<functor_type>().type_info();
out_buffer.type.const_qualified = false; out_buffer.members.type.const_qualified = false;
out_buffer.type.volatile_qualified = false; out_buffer.members.type.volatile_qualified = false;
return; return;
default: default:
@ -420,7 +418,7 @@ namespace boost {
// Function pointers // Function pointers
static inline void static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer, manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, function_ptr_tag) functor_manager_operation_type op, function_ptr_tag)
{ {
functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op); functor_manager_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
@ -428,15 +426,15 @@ namespace boost {
// Function objects that fit in the small-object buffer. // Function objects that fit in the small-object buffer.
static inline void static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer, manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, mpl::true_) functor_manager_operation_type op, mpl::true_)
{ {
functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op); functor_manager_common<Functor>::manage_small(in_buffer,out_buffer,op);
} }
// Function objects that require heap allocation // Function objects that require heap allocation
static inline void static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer, manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, mpl::false_) functor_manager_operation_type op, mpl::false_)
{ {
typedef functor_wrapper<Functor,Allocator> functor_wrapper_type; typedef functor_wrapper<Functor,Allocator> functor_wrapper_type;
@ -449,34 +447,34 @@ namespace boost {
// GCC 2.95.3 gets the CV qualifiers wrong here, so we // GCC 2.95.3 gets the CV qualifiers wrong here, so we
// can't do the static_cast that we should do. // can't do the static_cast that we should do.
const functor_wrapper_type* f = const functor_wrapper_type* f =
static_cast<const functor_wrapper_type*>(in_buffer.obj_ptr); static_cast<const functor_wrapper_type*>(in_buffer.members.obj_ptr);
wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*f)); wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*f));
wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1); wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
wrapper_allocator.construct(copy, *f); wrapper_allocator.construct(copy, *f);
// Get back to the original pointer type // Get back to the original pointer type
functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy); functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
out_buffer.obj_ptr = new_f; out_buffer.members.obj_ptr = new_f;
} else if (op == move_functor_tag) { } else if (op == move_functor_tag) {
out_buffer.obj_ptr = in_buffer.obj_ptr; out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
in_buffer.obj_ptr = 0; in_buffer.members.obj_ptr = 0;
} else if (op == destroy_functor_tag) { } else if (op == destroy_functor_tag) {
/* Cast from the void pointer to the functor_wrapper_type */ /* Cast from the void pointer to the functor_wrapper_type */
functor_wrapper_type* victim = functor_wrapper_type* victim =
static_cast<functor_wrapper_type*>(in_buffer.obj_ptr); static_cast<functor_wrapper_type*>(in_buffer.members.obj_ptr);
wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*victim)); wrapper_allocator_type wrapper_allocator(static_cast<Allocator const &>(*victim));
wrapper_allocator.destroy(victim); wrapper_allocator.destroy(victim);
wrapper_allocator.deallocate(victim,1); wrapper_allocator.deallocate(victim,1);
out_buffer.obj_ptr = 0; out_buffer.members.obj_ptr = 0;
} else if (op == check_functor_type_tag) { } else if (op == check_functor_type_tag) {
if (*out_buffer.type.type == boost::typeindex::type_id<Functor>()) if (*out_buffer.members.type.type == boost::typeindex::type_id<Functor>())
out_buffer.obj_ptr = in_buffer.obj_ptr; out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
else else
out_buffer.obj_ptr = 0; out_buffer.members.obj_ptr = 0;
} else /* op == get_functor_type_tag */ { } else /* op == get_functor_type_tag */ {
out_buffer.type.type = &boost::typeindex::type_id<Functor>().type_info(); out_buffer.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
out_buffer.type.const_qualified = false; out_buffer.members.type.const_qualified = false;
out_buffer.type.volatile_qualified = false; out_buffer.members.type.volatile_qualified = false;
} }
} }
@ -484,7 +482,7 @@ namespace boost {
// object can use the small-object optimization buffer or // object can use the small-object optimization buffer or
// whether we need to allocate it on the heap. // whether we need to allocate it on the heap.
static inline void static inline void
manager(const function_buffer& in_buffer, function_buffer& out_buffer, manager(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op, function_obj_tag) functor_manager_operation_type op, function_obj_tag)
{ {
manager(in_buffer, out_buffer, op, manager(in_buffer, out_buffer, op,
@ -495,15 +493,15 @@ namespace boost {
/* Dispatch to an appropriate manager based on whether we have a /* Dispatch to an appropriate manager based on whether we have a
function pointer or a function object pointer. */ function pointer or a function object pointer. */
static inline void static inline void
manage(const function_buffer& in_buffer, function_buffer& out_buffer, manage(const function_buffer& in_buffer, function_buffer& out_buffer,
functor_manager_operation_type op) functor_manager_operation_type op)
{ {
typedef typename get_function_tag<functor_type>::type tag_type; typedef typename get_function_tag<functor_type>::type tag_type;
switch (op) { switch (op) {
case get_functor_type_tag: case get_functor_type_tag:
out_buffer.type.type = &boost::typeindex::type_id<functor_type>().type_info(); out_buffer.members.type.type = &boost::typeindex::type_id<functor_type>().type_info();
out_buffer.type.const_qualified = false; out_buffer.members.type.const_qualified = false;
out_buffer.type.volatile_qualified = false; out_buffer.members.type.volatile_qualified = false;
return; return;
default: default:
@ -581,8 +579,8 @@ namespace boost {
*/ */
struct vtable_base struct vtable_base
{ {
void (*manager)(const function_buffer& in_buffer, void (*manager)(const function_buffer& in_buffer,
function_buffer& out_buffer, function_buffer& out_buffer,
functor_manager_operation_type op); functor_manager_operation_type op);
}; };
} // end namespace function } // end namespace function
@ -610,7 +608,7 @@ public:
detail::function::function_buffer type; detail::function::function_buffer type;
get_vtable()->manager(functor, type, detail::function::get_functor_type_tag); get_vtable()->manager(functor, type, detail::function::get_functor_type_tag);
return *type.type.type; return *type.members.type.type;
} }
template<typename Functor> template<typename Functor>
@ -619,12 +617,12 @@ public:
if (!vtable) return 0; if (!vtable) return 0;
detail::function::function_buffer type_result; detail::function::function_buffer type_result;
type_result.type.type = &boost::typeindex::type_id<Functor>().type_info(); type_result.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
type_result.type.const_qualified = is_const<Functor>::value; type_result.members.type.const_qualified = is_const<Functor>::value;
type_result.type.volatile_qualified = is_volatile<Functor>::value; type_result.members.type.volatile_qualified = is_volatile<Functor>::value;
get_vtable()->manager(functor, type_result, get_vtable()->manager(functor, type_result,
detail::function::check_functor_type_tag); detail::function::check_functor_type_tag);
return static_cast<Functor*>(type_result.obj_ptr); return static_cast<Functor*>(type_result.members.obj_ptr);
} }
template<typename Functor> template<typename Functor>
@ -633,14 +631,14 @@ public:
if (!vtable) return 0; if (!vtable) return 0;
detail::function::function_buffer type_result; detail::function::function_buffer type_result;
type_result.type.type = &boost::typeindex::type_id<Functor>().type_info(); type_result.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
type_result.type.const_qualified = true; type_result.members.type.const_qualified = true;
type_result.type.volatile_qualified = is_volatile<Functor>::value; type_result.members.type.volatile_qualified = is_volatile<Functor>::value;
get_vtable()->manager(functor, type_result, get_vtable()->manager(functor, type_result,
detail::function::check_functor_type_tag); detail::function::check_functor_type_tag);
// GCC 2.95.3 gets the CV qualifiers wrong here, so we // GCC 2.95.3 gets the CV qualifiers wrong here, so we
// can't do the static_cast that we should do. // can't do the static_cast that we should do.
return static_cast<const Functor*>(type_result.obj_ptr); return static_cast<const Functor*>(type_result.members.obj_ptr);
} }
template<typename F> template<typename F>

View File

@ -97,7 +97,7 @@ namespace boost {
static R invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA static R invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA
BOOST_FUNCTION_PARMS) BOOST_FUNCTION_PARMS)
{ {
FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr); FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.members.func_ptr);
return f(BOOST_FUNCTION_ARGS); return f(BOOST_FUNCTION_ARGS);
} }
}; };
@ -114,7 +114,7 @@ namespace boost {
BOOST_FUNCTION_PARMS) BOOST_FUNCTION_PARMS)
{ {
FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.func_ptr); FunctionPtr f = reinterpret_cast<FunctionPtr>(function_ptr.members.func_ptr);
BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS)); BOOST_FUNCTION_RETURN(f(BOOST_FUNCTION_ARGS));
} }
}; };
@ -134,7 +134,7 @@ namespace boost {
if (function_allows_small_object_optimization<FunctionObj>::value) if (function_allows_small_object_optimization<FunctionObj>::value)
f = reinterpret_cast<FunctionObj*>(function_obj_ptr.data); f = reinterpret_cast<FunctionObj*>(function_obj_ptr.data);
else else
f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr); f = reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr);
return (*f)(BOOST_FUNCTION_ARGS); return (*f)(BOOST_FUNCTION_ARGS);
} }
}; };
@ -155,7 +155,7 @@ namespace boost {
if (function_allows_small_object_optimization<FunctionObj>::value) if (function_allows_small_object_optimization<FunctionObj>::value)
f = reinterpret_cast<FunctionObj*>(function_obj_ptr.data); f = reinterpret_cast<FunctionObj*>(function_obj_ptr.data);
else else
f = reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr); f = reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr);
BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS)); BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
} }
}; };
@ -171,8 +171,8 @@ namespace boost {
BOOST_FUNCTION_PARMS) BOOST_FUNCTION_PARMS)
{ {
FunctionObj* f = FunctionObj* f =
reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr); reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr);
return (*f)(BOOST_FUNCTION_ARGS); return (*f)(BOOST_FUNCTION_ARGS);
} }
}; };
@ -189,8 +189,8 @@ namespace boost {
BOOST_FUNCTION_PARMS) BOOST_FUNCTION_PARMS)
{ {
FunctionObj* f = FunctionObj* f =
reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr); reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr);
BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS)); BOOST_FUNCTION_RETURN((*f)(BOOST_FUNCTION_ARGS));
} }
}; };
@ -208,7 +208,7 @@ namespace boost {
BOOST_FUNCTION_PARMS) BOOST_FUNCTION_PARMS)
{ {
MemberPtr* f = MemberPtr* f =
reinterpret_cast<MemberPtr*>(function_obj_ptr.data); reinterpret_cast<MemberPtr*>(function_obj_ptr.data);
return boost::mem_fn(*f)(BOOST_FUNCTION_ARGS); return boost::mem_fn(*f)(BOOST_FUNCTION_ARGS);
} }
@ -226,7 +226,7 @@ namespace boost {
BOOST_FUNCTION_PARMS) BOOST_FUNCTION_PARMS)
{ {
MemberPtr* f = MemberPtr* f =
reinterpret_cast<MemberPtr*>(function_obj_ptr.data); reinterpret_cast<MemberPtr*>(function_obj_ptr.data);
BOOST_FUNCTION_RETURN(boost::mem_fn(*f)(BOOST_FUNCTION_ARGS)); BOOST_FUNCTION_RETURN(boost::mem_fn(*f)(BOOST_FUNCTION_ARGS));
} }
@ -322,7 +322,7 @@ namespace boost {
/* Given the tag returned by get_function_tag, retrieve the /* Given the tag returned by get_function_tag, retrieve the
actual invoker that will be used for the given function actual invoker that will be used for the given function
object. object.
Each specialization contains an "apply" nested class template Each specialization contains an "apply" nested class template
that accepts the function object, return type, function that accepts the function object, return type, function
@ -513,21 +513,21 @@ namespace boost {
private: private:
// Function pointers // Function pointers
template<typename FunctionPtr> template<typename FunctionPtr>
bool bool
assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag) const assign_to(FunctionPtr f, function_buffer& functor, function_ptr_tag) const
{ {
this->clear(functor); this->clear(functor);
if (f) { if (f) {
// should be a reinterpret cast, but some compilers insist // should be a reinterpret cast, but some compilers insist
// on giving cv-qualifiers to free functions // on giving cv-qualifiers to free functions
functor.func_ptr = reinterpret_cast<void (*)()>(f); functor.members.func_ptr = reinterpret_cast<void (*)()>(f);
return true; return true;
} else { } else {
return false; return false;
} }
} }
template<typename FunctionPtr,typename Allocator> template<typename FunctionPtr,typename Allocator>
bool bool
assign_to_a(FunctionPtr f, function_buffer& functor, Allocator, function_ptr_tag) const assign_to_a(FunctionPtr f, function_buffer& functor, Allocator, function_ptr_tag) const
{ {
return assign_to(f,functor,function_ptr_tag()); return assign_to(f,functor,function_ptr_tag());
@ -566,13 +566,13 @@ namespace boost {
// Function objects // Function objects
// Assign to a function object using the small object optimization // Assign to a function object using the small object optimization
template<typename FunctionObj> template<typename FunctionObj>
void void
assign_functor(FunctionObj f, function_buffer& functor, mpl::true_) const assign_functor(FunctionObj f, function_buffer& functor, mpl::true_) const
{ {
new (reinterpret_cast<void*>(functor.data)) FunctionObj(f); new (reinterpret_cast<void*>(functor.data)) FunctionObj(f);
} }
template<typename FunctionObj,typename Allocator> template<typename FunctionObj,typename Allocator>
void void
assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, mpl::true_) const assign_functor_a(FunctionObj f, function_buffer& functor, Allocator, mpl::true_) const
{ {
assign_functor(f,functor,mpl::true_()); assign_functor(f,functor,mpl::true_());
@ -580,13 +580,13 @@ namespace boost {
// Assign to a function object allocated on the heap. // Assign to a function object allocated on the heap.
template<typename FunctionObj> template<typename FunctionObj>
void void
assign_functor(FunctionObj f, function_buffer& functor, mpl::false_) const assign_functor(FunctionObj f, function_buffer& functor, mpl::false_) const
{ {
functor.obj_ptr = new FunctionObj(f); functor.members.obj_ptr = new FunctionObj(f);
} }
template<typename FunctionObj,typename Allocator> template<typename FunctionObj,typename Allocator>
void void
assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, mpl::false_) const assign_functor_a(FunctionObj f, function_buffer& functor, Allocator a, mpl::false_) const
{ {
typedef functor_wrapper<FunctionObj,Allocator> functor_wrapper_type; typedef functor_wrapper<FunctionObj,Allocator> functor_wrapper_type;
@ -597,15 +597,15 @@ namespace boost {
wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1); wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
wrapper_allocator.construct(copy, functor_wrapper_type(f,a)); wrapper_allocator.construct(copy, functor_wrapper_type(f,a));
functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy); functor_wrapper_type* new_f = static_cast<functor_wrapper_type*>(copy);
functor.obj_ptr = new_f; functor.members.obj_ptr = new_f;
} }
template<typename FunctionObj> template<typename FunctionObj>
bool bool
assign_to(FunctionObj f, function_buffer& functor, function_obj_tag) const assign_to(FunctionObj f, function_buffer& functor, function_obj_tag) const
{ {
if (!boost::detail::function::has_empty_target(boost::addressof(f))) { if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
assign_functor(f, functor, assign_functor(f, functor,
mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>()); mpl::bool_<(function_allows_small_object_optimization<FunctionObj>::value)>());
return true; return true;
} else { } else {
@ -613,7 +613,7 @@ namespace boost {
} }
} }
template<typename FunctionObj,typename Allocator> template<typename FunctionObj,typename Allocator>
bool bool
assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag) const assign_to_a(FunctionObj f, function_buffer& functor, Allocator a, function_obj_tag) const
{ {
if (!boost::detail::function::has_empty_target(boost::addressof(f))) { if (!boost::detail::function::has_empty_target(boost::addressof(f))) {
@ -627,18 +627,18 @@ namespace boost {
// Reference to a function object // Reference to a function object
template<typename FunctionObj> template<typename FunctionObj>
bool bool
assign_to(const reference_wrapper<FunctionObj>& f, assign_to(const reference_wrapper<FunctionObj>& f,
function_buffer& functor, function_obj_ref_tag) const function_buffer& functor, function_obj_ref_tag) const
{ {
functor.obj_ref.obj_ptr = (void *)(f.get_pointer()); functor.members.obj_ref.obj_ptr = (void *)(f.get_pointer());
functor.obj_ref.is_const_qualified = is_const<FunctionObj>::value; functor.members.obj_ref.is_const_qualified = is_const<FunctionObj>::value;
functor.obj_ref.is_volatile_qualified = is_volatile<FunctionObj>::value; functor.members.obj_ref.is_volatile_qualified = is_volatile<FunctionObj>::value;
return true; return true;
} }
template<typename FunctionObj,typename Allocator> template<typename FunctionObj,typename Allocator>
bool bool
assign_to_a(const reference_wrapper<FunctionObj>& f, assign_to_a(const reference_wrapper<FunctionObj>& f,
function_buffer& functor, Allocator, function_obj_ref_tag) const function_buffer& functor, Allocator, function_obj_ref_tag) const
{ {
return assign_to(f,functor,function_obj_ref_tag()); return assign_to(f,functor,function_obj_ref_tag());
@ -921,7 +921,7 @@ namespace boost {
typedef typename boost::detail::function::get_function_tag<Functor>::type tag; typedef typename boost::detail::function::get_function_tag<Functor>::type tag;
typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker; typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
typedef typename get_invoker:: typedef typename get_invoker::
template apply<Functor, R BOOST_FUNCTION_COMMA template apply<Functor, R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS> BOOST_FUNCTION_TEMPLATE_ARGS>
handler_type; handler_type;
@ -932,7 +932,7 @@ namespace boost {
// static initialization. Otherwise, we will have a race // static initialization. Otherwise, we will have a race
// condition here in multi-threaded code. See // condition here in multi-threaded code. See
// http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/. // http://thread.gmane.org/gmane.comp.lib.boost.devel/164902/.
static const vtable_type stored_vtable = static const vtable_type stored_vtable =
{ { &manager_type::manage }, &invoker_type::invoke }; { { &manager_type::manage }, &invoker_type::invoke };
if (stored_vtable.assign_to(f, functor)) { if (stored_vtable.assign_to(f, functor)) {
@ -943,7 +943,7 @@ namespace boost {
boost::detail::function::function_allows_small_object_optimization<Functor>::value) boost::detail::function::function_allows_small_object_optimization<Functor>::value)
value |= static_cast<std::size_t>(0x01); value |= static_cast<std::size_t>(0x01);
vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value); vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value);
} else } else
vtable = 0; vtable = 0;
} }
@ -955,7 +955,7 @@ namespace boost {
typedef typename boost::detail::function::get_function_tag<Functor>::type tag; typedef typename boost::detail::function::get_function_tag<Functor>::type tag;
typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker; typedef boost::detail::function::BOOST_FUNCTION_GET_INVOKER<tag> get_invoker;
typedef typename get_invoker:: typedef typename get_invoker::
template apply_a<Functor, R BOOST_FUNCTION_COMMA template apply_a<Functor, R BOOST_FUNCTION_COMMA
BOOST_FUNCTION_TEMPLATE_ARGS, BOOST_FUNCTION_TEMPLATE_ARGS,
Allocator> Allocator>
handler_type; handler_type;
@ -970,7 +970,7 @@ namespace boost {
static const vtable_type stored_vtable = static const vtable_type stored_vtable =
{ { &manager_type::manage }, &invoker_type::invoke }; { { &manager_type::manage }, &invoker_type::invoke };
if (stored_vtable.assign_to_a(f, functor, a)) { if (stored_vtable.assign_to_a(f, functor, a)) {
std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base); std::size_t value = reinterpret_cast<std::size_t>(&stored_vtable.base);
// coverity[pointless_expression]: suppress coverity warnings on apparant if(const). // coverity[pointless_expression]: suppress coverity warnings on apparant if(const).
if (boost::has_trivial_copy_constructor<Functor>::value && if (boost::has_trivial_copy_constructor<Functor>::value &&
@ -978,14 +978,14 @@ namespace boost {
boost::detail::function::function_allows_small_object_optimization<Functor>::value) boost::detail::function::function_allows_small_object_optimization<Functor>::value)
value |= static_cast<std::size_t>(0x01); value |= static_cast<std::size_t>(0x01);
vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value); vtable = reinterpret_cast<boost::detail::function::vtable_base *>(value);
} else } else
vtable = 0; vtable = 0;
} }
// Moves the value from the specified argument to *this. If the argument // Moves the value from the specified argument to *this. If the argument
// has its function object allocated on the heap, move_assign will pass // has its function object allocated on the heap, move_assign will pass
// its buffer to *this, and set the argument's buffer pointer to NULL. // its buffer to *this, and set the argument's buffer pointer to NULL.
void move_assign(BOOST_FUNCTION_FUNCTION& f) void move_assign(BOOST_FUNCTION_FUNCTION& f)
{ {
if (&f == this) if (&f == this)
return; return;
@ -1139,7 +1139,7 @@ public:
self_type(f).swap(*this); self_type(f).swap(*this);
return *this; return *this;
} }
#ifndef BOOST_NO_CXX11_RVALUE_REFERENCES #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
self_type& operator=(base_type&& f) self_type& operator=(base_type&& f)
{ {