Boost logo

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