forked from boostorg/function
Changed implementation to avoid calculating the size of the raw data buffer manually. Trim trailing spaces.
This commit is contained in:
@ -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)];
|
||||
};
|
||||
|
||||
/**
|
||||
@ -176,42 +174,42 @@ namespace boost {
|
||||
struct reference_manager
|
||||
{
|
||||
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)
|
||||
{
|
||||
switch (op) {
|
||||
case clone_functor_tag:
|
||||
out_buffer.obj_ref = in_buffer.obj_ref;
|
||||
case clone_functor_tag:
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -225,9 +223,9 @@ namespace boost {
|
||||
struct function_allows_small_object_optimization
|
||||
{
|
||||
BOOST_STATIC_CONSTANT
|
||||
(bool,
|
||||
(bool,
|
||||
value = ((sizeof(F) <= sizeof(function_buffer) &&
|
||||
(alignment_of<function_buffer>::value
|
||||
(alignment_of<function_buffer>::value
|
||||
% alignment_of<F>::value == 0))));
|
||||
};
|
||||
|
||||
@ -239,7 +237,7 @@ namespace boost {
|
||||
A(a)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
functor_wrapper(const functor_wrapper& f) :
|
||||
F(static_cast<const F&>(f)),
|
||||
A(static_cast<const A&>(f))
|
||||
@ -258,35 +256,35 @@ namespace boost {
|
||||
|
||||
// Function pointers
|
||||
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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// Function objects that fit in the small-object buffer.
|
||||
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)
|
||||
{
|
||||
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);
|
||||
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)
|
||||
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;
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -321,7 +319,7 @@ namespace boost {
|
||||
|
||||
// Function pointers
|
||||
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_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
|
||||
@ -329,15 +327,15 @@ namespace boost {
|
||||
|
||||
// Function objects that fit in the small-object buffer.
|
||||
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_common<Functor>::manage_small(in_buffer,out_buffer,op);
|
||||
}
|
||||
|
||||
|
||||
// Function objects that require heap allocation
|
||||
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_)
|
||||
{
|
||||
if (op == clone_functor_tag) {
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -375,7 +373,7 @@ namespace boost {
|
||||
// object can use the small-object optimization buffer or
|
||||
// whether we need to allocate it on the heap.
|
||||
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)
|
||||
{
|
||||
manager(in_buffer, out_buffer, op,
|
||||
@ -384,7 +382,7 @@ namespace boost {
|
||||
|
||||
// For member pointers, we use the small-object optimization buffer.
|
||||
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)
|
||||
{
|
||||
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
|
||||
function pointer or a function object pointer. */
|
||||
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)
|
||||
{
|
||||
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:
|
||||
@ -420,7 +418,7 @@ namespace boost {
|
||||
|
||||
// Function pointers
|
||||
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_common<Functor>::manage_ptr(in_buffer,out_buffer,op);
|
||||
@ -428,15 +426,15 @@ namespace boost {
|
||||
|
||||
// Function objects that fit in the small-object buffer.
|
||||
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_common<Functor>::manage_small(in_buffer,out_buffer,op);
|
||||
}
|
||||
|
||||
|
||||
// Function objects that require heap allocation
|
||||
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_)
|
||||
{
|
||||
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
|
||||
// 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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -484,7 +482,7 @@ namespace boost {
|
||||
// object can use the small-object optimization buffer or
|
||||
// whether we need to allocate it on the heap.
|
||||
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)
|
||||
{
|
||||
manager(in_buffer, out_buffer, op,
|
||||
@ -495,15 +493,15 @@ namespace boost {
|
||||
/* Dispatch to an appropriate manager based on whether we have a
|
||||
function pointer or a function object pointer. */
|
||||
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)
|
||||
{
|
||||
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:
|
||||
@ -581,8 +579,8 @@ namespace boost {
|
||||
*/
|
||||
struct vtable_base
|
||||
{
|
||||
void (*manager)(const function_buffer& in_buffer,
|
||||
function_buffer& out_buffer,
|
||||
void (*manager)(const function_buffer& in_buffer,
|
||||
function_buffer& out_buffer,
|
||||
functor_manager_operation_type op);
|
||||
};
|
||||
} // end namespace function
|
||||
@ -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;
|
||||
get_vtable()->manager(functor, type_result,
|
||||
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;
|
||||
get_vtable()->manager(functor, type_result,
|
||||
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>
|
||||
|
Reference in New Issue
Block a user