|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r48627 - in trunk: boost/function libs/function/test
From: dgregor_at_[hidden]
Date: 2008-09-05 23:16:25
Author: dgregor
Date: 2008-09-05 23:16:25 EDT (Fri, 05 Sep 2008)
New Revision: 48627
URL: http://svn.boost.org/trac/boost/changeset/48627
Log:
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.
Text files modified:
trunk/boost/function/function_base.hpp | 18 +++++++-------
trunk/boost/function/function_template.hpp | 5 ++-
trunk/libs/function/test/function_n_test.cpp | 47 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 59 insertions(+), 11 deletions(-)
Modified: trunk/boost/function/function_base.hpp
==============================================================================
--- trunk/boost/function/function_base.hpp (original)
+++ trunk/boost/function/function_base.hpp 2008-09-05 23:16:25 EDT (Fri, 05 Sep 2008)
@@ -99,12 +99,12 @@
// For pointers to std::type_info objects
struct type_t {
// (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.
- bool const_qualified : 1;
+ bool const_qualified;
// Whether the type is volatile-qualified.
- bool volatile_qualified : 1;
+ bool volatile_qualified;
} type;
// For function pointers of all kinds
@@ -120,8 +120,8 @@
// track of the cv-qualifiers on the object referenced.
struct obj_ref_t {
mutable void* obj_ptr;
- bool is_const : 1;
- bool is_volatile : 1;
+ bool is_const_qualified;
+ bool is_volatile_qualified;
} obj_ref;
// To relax aliasing constraints
@@ -217,9 +217,9 @@
// Check whether we have the same type. We can add
// cv-qualifiers, but we can't take them away.
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)
- && (!in_buffer.obj_ref.is_volatile
+ && (!in_buffer.obj_ref.is_volatile_qualified
|| out_buffer.type.volatile_qualified))
out_buffer.obj_ptr = in_buffer.obj_ref.obj_ptr;
else
@@ -229,8 +229,8 @@
case get_functor_type_tag:
out_buffer.type.type = &typeid(F);
- out_buffer.type.const_qualified = in_buffer.obj_ref.is_const;
- out_buffer.type.volatile_qualified = in_buffer.obj_ref.is_volatile;
+ out_buffer.type.const_qualified = in_buffer.obj_ref.is_const_qualified;
+ out_buffer.type.volatile_qualified = in_buffer.obj_ref.is_volatile_qualified;
return;
}
}
Modified: trunk/boost/function/function_template.hpp
==============================================================================
--- trunk/boost/function/function_template.hpp (original)
+++ trunk/boost/function/function_template.hpp 2008-09-05 23:16:25 EDT (Fri, 05 Sep 2008)
@@ -517,8 +517,8 @@
{
if (!boost::detail::function::has_empty_target(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_volatile = is_volatile<FunctionObj>::value;
+ functor.obj_ref.is_const_qualified = is_const<FunctionObj>::value;
+ functor.obj_ref.is_volatile_qualified = is_volatile<FunctionObj>::value;
return true;
} else {
return false;
@@ -801,6 +801,7 @@
this->vtable = f.vtable;
f.vtable->manager(f.functor, this->functor,
boost::detail::function::move_functor_tag);
+ f.vtable = 0;
#if !defined(BOOST_NO_EXCEPTIONS)
} else {
clear();
Modified: trunk/libs/function/test/function_n_test.cpp
==============================================================================
--- trunk/libs/function/test/function_n_test.cpp (original)
+++ trunk/libs/function/test/function_n_test.cpp 2008-09-05 23:16:25 EDT (Fri, 05 Sep 2008)
@@ -636,6 +636,52 @@
}
}
+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* [])
{
test_zero_args();
@@ -644,5 +690,6 @@
test_emptiness();
test_member_functions();
test_ref();
+ test_construct_destroy_count();
return 0;
}
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk