mirror of
https://github.com/boostorg/function.git
synced 2025-07-13 12:46:34 +02:00
Fix double-destruction problem with small function objects and swap(), and try to work around a GCC 4.2 issue. See #1910 for comments about the former problem from Niels Dekker.
[SVN r48627]
This commit is contained in:
@ -99,12 +99,12 @@ namespace boost {
|
|||||||
// For pointers to std::type_info objects
|
// For pointers to std::type_info objects
|
||||||
struct type_t {
|
struct type_t {
|
||||||
// (get_functor_type_tag, check_functor_type_tag).
|
// (get_functor_type_tag, check_functor_type_tag).
|
||||||
const std::type_info* type;
|
const BOOST_FUNCTION_STD_NS::type_info* type;
|
||||||
|
|
||||||
// Whether the type is const-qualified.
|
// Whether the type is const-qualified.
|
||||||
bool const_qualified : 1;
|
bool const_qualified;
|
||||||
// Whether the type is volatile-qualified.
|
// Whether the type is volatile-qualified.
|
||||||
bool volatile_qualified : 1;
|
bool volatile_qualified;
|
||||||
} type;
|
} type;
|
||||||
|
|
||||||
// For function pointers of all kinds
|
// For function pointers of all kinds
|
||||||
@ -120,8 +120,8 @@ namespace boost {
|
|||||||
// track of the cv-qualifiers on the object referenced.
|
// track of the cv-qualifiers on the object referenced.
|
||||||
struct obj_ref_t {
|
struct obj_ref_t {
|
||||||
mutable void* obj_ptr;
|
mutable void* obj_ptr;
|
||||||
bool is_const : 1;
|
bool is_const_qualified;
|
||||||
bool is_volatile : 1;
|
bool is_volatile_qualified;
|
||||||
} obj_ref;
|
} obj_ref;
|
||||||
|
|
||||||
// To relax aliasing constraints
|
// To relax aliasing constraints
|
||||||
@ -217,9 +217,9 @@ namespace boost {
|
|||||||
// 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 (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(F))
|
if (BOOST_FUNCTION_COMPARE_TYPE_ID(check_type, typeid(F))
|
||||||
&& (!in_buffer.obj_ref.is_const
|
&& (!in_buffer.obj_ref.is_const_qualified
|
||||||
|| out_buffer.type.const_qualified)
|
|| out_buffer.type.const_qualified)
|
||||||
&& (!in_buffer.obj_ref.is_volatile
|
&& (!in_buffer.obj_ref.is_volatile_qualified
|
||||||
|| out_buffer.type.volatile_qualified))
|
|| out_buffer.type.volatile_qualified))
|
||||||
out_buffer.obj_ptr = in_buffer.obj_ref.obj_ptr;
|
out_buffer.obj_ptr = in_buffer.obj_ref.obj_ptr;
|
||||||
else
|
else
|
||||||
@ -229,8 +229,8 @@ namespace boost {
|
|||||||
|
|
||||||
case get_functor_type_tag:
|
case get_functor_type_tag:
|
||||||
out_buffer.type.type = &typeid(F);
|
out_buffer.type.type = &typeid(F);
|
||||||
out_buffer.type.const_qualified = in_buffer.obj_ref.is_const;
|
out_buffer.type.const_qualified = in_buffer.obj_ref.is_const_qualified;
|
||||||
out_buffer.type.volatile_qualified = in_buffer.obj_ref.is_volatile;
|
out_buffer.type.volatile_qualified = in_buffer.obj_ref.is_volatile_qualified;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -517,8 +517,8 @@ namespace boost {
|
|||||||
{
|
{
|
||||||
if (!boost::detail::function::has_empty_target(f.get_pointer())) {
|
if (!boost::detail::function::has_empty_target(f.get_pointer())) {
|
||||||
functor.obj_ref.obj_ptr = (void *)f.get_pointer();
|
functor.obj_ref.obj_ptr = (void *)f.get_pointer();
|
||||||
functor.obj_ref.is_const = is_const<FunctionObj>::value;
|
functor.obj_ref.is_const_qualified = is_const<FunctionObj>::value;
|
||||||
functor.obj_ref.is_volatile = is_volatile<FunctionObj>::value;
|
functor.obj_ref.is_volatile_qualified = is_volatile<FunctionObj>::value;
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
@ -801,6 +801,7 @@ namespace boost {
|
|||||||
this->vtable = f.vtable;
|
this->vtable = f.vtable;
|
||||||
f.vtable->manager(f.functor, this->functor,
|
f.vtable->manager(f.functor, this->functor,
|
||||||
boost::detail::function::move_functor_tag);
|
boost::detail::function::move_functor_tag);
|
||||||
|
f.vtable = 0;
|
||||||
#if !defined(BOOST_NO_EXCEPTIONS)
|
#if !defined(BOOST_NO_EXCEPTIONS)
|
||||||
} else {
|
} else {
|
||||||
clear();
|
clear();
|
||||||
|
@ -636,6 +636,52 @@ test_ref()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static unsigned construction_count = 0;
|
||||||
|
static unsigned destruction_count = 0;
|
||||||
|
|
||||||
|
struct MySmallFunctor {
|
||||||
|
MySmallFunctor() { ++construction_count; }
|
||||||
|
MySmallFunctor(const MySmallFunctor &) { ++construction_count; }
|
||||||
|
~MySmallFunctor() { ++destruction_count; }
|
||||||
|
int operator()() { return 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
struct MyLargeFunctor {
|
||||||
|
MyLargeFunctor() { ++construction_count; }
|
||||||
|
MyLargeFunctor(const MyLargeFunctor &) { ++construction_count; }
|
||||||
|
~MyLargeFunctor() { ++destruction_count; }
|
||||||
|
int operator()() { return 0; }
|
||||||
|
};
|
||||||
|
|
||||||
|
void test_construct_destroy_count()
|
||||||
|
{
|
||||||
|
{
|
||||||
|
boost::function0<int> f;
|
||||||
|
boost::function0<int> g;
|
||||||
|
f = MySmallFunctor();
|
||||||
|
g = MySmallFunctor();
|
||||||
|
f.swap(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MySmallFunctor objects should be constructed as many times as
|
||||||
|
// they are destroyed.
|
||||||
|
BOOST_CHECK(construction_count == destruction_count);
|
||||||
|
|
||||||
|
construction_count = 0;
|
||||||
|
destruction_count = 0;
|
||||||
|
{
|
||||||
|
boost::function0<int> f;
|
||||||
|
boost::function0<int> g;
|
||||||
|
f = MyLargeFunctor();
|
||||||
|
g = MyLargeFunctor();
|
||||||
|
f.swap(g);
|
||||||
|
}
|
||||||
|
|
||||||
|
// MyLargeFunctor objects should be constructed as many times as
|
||||||
|
// they are destroyed.
|
||||||
|
BOOST_CHECK(construction_count == destruction_count);
|
||||||
|
}
|
||||||
|
|
||||||
int test_main(int, char* [])
|
int test_main(int, char* [])
|
||||||
{
|
{
|
||||||
test_zero_args();
|
test_zero_args();
|
||||||
@ -644,5 +690,6 @@ int test_main(int, char* [])
|
|||||||
test_emptiness();
|
test_emptiness();
|
||||||
test_member_functions();
|
test_member_functions();
|
||||||
test_ref();
|
test_ref();
|
||||||
|
test_construct_destroy_count();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user