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
* member function pointer.
*/
union function_buffer
union function_buffer_members
{
// For pointers to function objects
typedef void* obj_ptr_t;
@ -99,17 +99,15 @@ namespace boost {
bool is_const_qualified;
bool is_volatile_qualified;
} obj_ref;
enum {
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),
size3 = size2 > sizeof(bound_memfunc_ptr_t) ? size2 : sizeof(bound_memfunc_ptr_t),
size4 = size3 > sizeof(obj_ref_t) ? size3 : sizeof(obj_ref_t),
data_size = size4
};
union function_buffer
{
// Type-specific union members
mutable function_buffer_members members;
// To relax aliasing constraints
mutable char data[data_size];
mutable char data[sizeof(function_buffer_members)];
};
/**
@ -181,37 +179,37 @@ namespace boost {
{
switch (op) {
case clone_functor_tag:
out_buffer.obj_ref = in_buffer.obj_ref;
out_buffer.members.obj_ref = in_buffer.members.obj_ref;
return;
case move_functor_tag:
out_buffer.obj_ref = in_buffer.obj_ref;
in_buffer.obj_ref.obj_ptr = 0;
out_buffer.members.obj_ref = in_buffer.members.obj_ref;
in_buffer.members.obj_ref.obj_ptr = 0;
return;
case destroy_functor_tag:
out_buffer.obj_ref.obj_ptr = 0;
out_buffer.members.obj_ref.obj_ptr = 0;
return;
case check_functor_type_tag:
{
// Check whether we have the same type. We can add
// cv-qualifiers, but we can't take them away.
if (*out_buffer.type.type == boost::typeindex::type_id<F>()
&& (!in_buffer.obj_ref.is_const_qualified
|| out_buffer.type.const_qualified)
&& (!in_buffer.obj_ref.is_volatile_qualified
|| out_buffer.type.volatile_qualified))
out_buffer.obj_ptr = in_buffer.obj_ref.obj_ptr;
if (*out_buffer.members.type.type == boost::typeindex::type_id<F>()
&& (!in_buffer.members.obj_ref.is_const_qualified
|| out_buffer.members.type.const_qualified)
&& (!in_buffer.members.obj_ref.is_volatile_qualified
|| out_buffer.members.type.volatile_qualified))
out_buffer.members.obj_ptr = in_buffer.members.obj_ref.obj_ptr;
else
out_buffer.obj_ptr = 0;
out_buffer.members.obj_ptr = 0;
}
return;
case get_functor_type_tag:
out_buffer.type.type = &boost::typeindex::type_id<F>().type_info();
out_buffer.type.const_qualified = in_buffer.obj_ref.is_const_qualified;
out_buffer.type.volatile_qualified = in_buffer.obj_ref.is_volatile_qualified;
out_buffer.members.type.type = &boost::typeindex::type_id<F>().type_info();
out_buffer.members.type.const_qualified = in_buffer.members.obj_ref.is_const_qualified;
out_buffer.members.type.volatile_qualified = in_buffer.members.obj_ref.is_volatile_qualified;
return;
}
}
@ -262,21 +260,21 @@ namespace boost {
functor_manager_operation_type op)
{
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) {
out_buffer.func_ptr = in_buffer.func_ptr;
in_buffer.func_ptr = 0;
out_buffer.members.func_ptr = in_buffer.members.func_ptr;
in_buffer.members.func_ptr = 0;
} else if (op == destroy_functor_tag)
out_buffer.func_ptr = 0;
out_buffer.members.func_ptr = 0;
else if (op == check_functor_type_tag) {
if (*out_buffer.type.type == boost::typeindex::type_id<Functor>())
out_buffer.obj_ptr = &in_buffer.func_ptr;
if (*out_buffer.members.type.type == boost::typeindex::type_id<Functor>())
out_buffer.members.obj_ptr = &in_buffer.members.func_ptr;
else
out_buffer.obj_ptr = 0;
out_buffer.members.obj_ptr = 0;
} else /* op == get_functor_type_tag */ {
out_buffer.type.type = &boost::typeindex::type_id<Functor>().type_info();
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
out_buffer.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
out_buffer.members.type.const_qualified = false;
out_buffer.members.type.volatile_qualified = false;
}
}
@ -301,14 +299,14 @@ namespace boost {
(void)f; // suppress warning about the value of f not being used (MSVC)
f->~Functor();
} else if (op == check_functor_type_tag) {
if (*out_buffer.type.type == boost::typeindex::type_id<Functor>())
out_buffer.obj_ptr = in_buffer.data;
if (*out_buffer.members.type.type == boost::typeindex::type_id<Functor>())
out_buffer.members.obj_ptr = in_buffer.data;
else
out_buffer.obj_ptr = 0;
out_buffer.members.obj_ptr = 0;
} else /* op == get_functor_type_tag */ {
out_buffer.type.type = &boost::typeindex::type_id<Functor>().type_info();
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
out_buffer.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
out_buffer.members.type.const_qualified = false;
out_buffer.members.type.volatile_qualified = false;
}
}
};
@ -347,27 +345,27 @@ namespace boost {
// jewillco: Changing this to static_cast because GCC 2.95.3 is
// obsolete.
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);
out_buffer.obj_ptr = new_f;
out_buffer.members.obj_ptr = new_f;
} else if (op == move_functor_tag) {
out_buffer.obj_ptr = in_buffer.obj_ptr;
in_buffer.obj_ptr = 0;
out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
in_buffer.members.obj_ptr = 0;
} else if (op == destroy_functor_tag) {
/* Cast from the void pointer to the functor pointer type */
functor_type* f =
static_cast<functor_type*>(out_buffer.obj_ptr);
static_cast<functor_type*>(out_buffer.members.obj_ptr);
delete f;
out_buffer.obj_ptr = 0;
out_buffer.members.obj_ptr = 0;
} else if (op == check_functor_type_tag) {
if (*out_buffer.type.type == boost::typeindex::type_id<Functor>())
out_buffer.obj_ptr = in_buffer.obj_ptr;
if (*out_buffer.members.type.type == boost::typeindex::type_id<Functor>())
out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
else
out_buffer.obj_ptr = 0;
out_buffer.members.obj_ptr = 0;
} else /* op == get_functor_type_tag */ {
out_buffer.type.type = &boost::typeindex::type_id<Functor>().type_info();
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
out_buffer.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
out_buffer.members.type.const_qualified = false;
out_buffer.members.type.volatile_qualified = false;
}
}
@ -400,9 +398,9 @@ namespace boost {
typedef typename get_function_tag<functor_type>::type tag_type;
switch (op) {
case get_functor_type_tag:
out_buffer.type.type = &boost::typeindex::type_id<functor_type>().type_info();
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
out_buffer.members.type.type = &boost::typeindex::type_id<functor_type>().type_info();
out_buffer.members.type.const_qualified = false;
out_buffer.members.type.volatile_qualified = false;
return;
default:
@ -449,34 +447,34 @@ namespace boost {
// GCC 2.95.3 gets the CV qualifiers wrong here, so we
// can't do the static_cast that we should do.
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_pointer_type copy = wrapper_allocator.allocate(1);
wrapper_allocator.construct(copy, *f);
// Get back to the original pointer type
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) {
out_buffer.obj_ptr = in_buffer.obj_ptr;
in_buffer.obj_ptr = 0;
out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
in_buffer.members.obj_ptr = 0;
} else if (op == destroy_functor_tag) {
/* Cast from the void pointer to the functor_wrapper_type */
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.destroy(victim);
wrapper_allocator.deallocate(victim,1);
out_buffer.obj_ptr = 0;
out_buffer.members.obj_ptr = 0;
} else if (op == check_functor_type_tag) {
if (*out_buffer.type.type == boost::typeindex::type_id<Functor>())
out_buffer.obj_ptr = in_buffer.obj_ptr;
if (*out_buffer.members.type.type == boost::typeindex::type_id<Functor>())
out_buffer.members.obj_ptr = in_buffer.members.obj_ptr;
else
out_buffer.obj_ptr = 0;
out_buffer.members.obj_ptr = 0;
} else /* op == get_functor_type_tag */ {
out_buffer.type.type = &boost::typeindex::type_id<Functor>().type_info();
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
out_buffer.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
out_buffer.members.type.const_qualified = false;
out_buffer.members.type.volatile_qualified = false;
}
}
@ -501,9 +499,9 @@ namespace boost {
typedef typename get_function_tag<functor_type>::type tag_type;
switch (op) {
case get_functor_type_tag:
out_buffer.type.type = &boost::typeindex::type_id<functor_type>().type_info();
out_buffer.type.const_qualified = false;
out_buffer.type.volatile_qualified = false;
out_buffer.members.type.type = &boost::typeindex::type_id<functor_type>().type_info();
out_buffer.members.type.const_qualified = false;
out_buffer.members.type.volatile_qualified = false;
return;
default:
@ -610,7 +608,7 @@ public:
detail::function::function_buffer type;
get_vtable()->manager(functor, type, detail::function::get_functor_type_tag);
return *type.type.type;
return *type.members.type.type;
}
template<typename Functor>
@ -619,12 +617,12 @@ public:
if (!vtable) return 0;
detail::function::function_buffer type_result;
type_result.type.type = &boost::typeindex::type_id<Functor>().type_info();
type_result.type.const_qualified = is_const<Functor>::value;
type_result.type.volatile_qualified = is_volatile<Functor>::value;
type_result.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
type_result.members.type.const_qualified = is_const<Functor>::value;
type_result.members.type.volatile_qualified = is_volatile<Functor>::value;
get_vtable()->manager(functor, type_result,
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>
@ -633,14 +631,14 @@ public:
if (!vtable) return 0;
detail::function::function_buffer type_result;
type_result.type.type = &boost::typeindex::type_id<Functor>().type_info();
type_result.type.const_qualified = true;
type_result.type.volatile_qualified = is_volatile<Functor>::value;
type_result.members.type.type = &boost::typeindex::type_id<Functor>().type_info();
type_result.members.type.const_qualified = true;
type_result.members.type.volatile_qualified = is_volatile<Functor>::value;
get_vtable()->manager(functor, type_result,
detail::function::check_functor_type_tag);
// GCC 2.95.3 gets the CV qualifiers wrong here, so we
// 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>

View File

@ -97,7 +97,7 @@ namespace boost {
static R invoke(function_buffer& function_ptr BOOST_FUNCTION_COMMA
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);
}
};
@ -114,7 +114,7 @@ namespace boost {
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));
}
};
@ -134,7 +134,7 @@ namespace boost {
if (function_allows_small_object_optimization<FunctionObj>::value)
f = reinterpret_cast<FunctionObj*>(function_obj_ptr.data);
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);
}
};
@ -155,7 +155,7 @@ namespace boost {
if (function_allows_small_object_optimization<FunctionObj>::value)
f = reinterpret_cast<FunctionObj*>(function_obj_ptr.data);
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));
}
};
@ -172,7 +172,7 @@ namespace boost {
{
FunctionObj* f =
reinterpret_cast<FunctionObj*>(function_obj_ptr.obj_ptr);
reinterpret_cast<FunctionObj*>(function_obj_ptr.members.obj_ptr);
return (*f)(BOOST_FUNCTION_ARGS);
}
};
@ -190,7 +190,7 @@ namespace boost {
{
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));
}
};
@ -520,7 +520,7 @@ namespace boost {
if (f) {
// should be a reinterpret cast, but some compilers insist
// on giving cv-qualifiers to free functions
functor.func_ptr = reinterpret_cast<void (*)()>(f);
functor.members.func_ptr = reinterpret_cast<void (*)()>(f);
return true;
} else {
return false;
@ -583,7 +583,7 @@ namespace boost {
void
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>
void
@ -597,7 +597,7 @@ namespace boost {
wrapper_allocator_pointer_type copy = wrapper_allocator.allocate(1);
wrapper_allocator.construct(copy, functor_wrapper_type(f,a));
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>
@ -631,9 +631,9 @@ namespace boost {
assign_to(const reference_wrapper<FunctionObj>& f,
function_buffer& functor, function_obj_ref_tag) const
{
functor.obj_ref.obj_ptr = (void *)(f.get_pointer());
functor.obj_ref.is_const_qualified = is_const<FunctionObj>::value;
functor.obj_ref.is_volatile_qualified = is_volatile<FunctionObj>::value;
functor.members.obj_ref.obj_ptr = (void *)(f.get_pointer());
functor.members.obj_ref.is_const_qualified = is_const<FunctionObj>::value;
functor.members.obj_ref.is_volatile_qualified = is_volatile<FunctionObj>::value;
return true;
}
template<typename FunctionObj,typename Allocator>