$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r55689 - in sandbox/fmhess: boost/generic_ptr libs/generic_ptr/test
From: fmhess_at_[hidden]
Date: 2009-08-20 14:51:52
Author: fmhess
Date: 2009-08-20 14:51:51 EDT (Thu, 20 Aug 2009)
New Revision: 55689
URL: http://svn.boost.org/trac/boost/changeset/55689
Log:
Optimized generic_ptr::cloning to only perform a single heap
allocation on copying.  generic_ptr::cloning no longer takes 
ownership of the pointer it was initially constructed from.
Text files modified: 
   sandbox/fmhess/boost/generic_ptr/cloning.hpp          |   111 ++++++++++++++++++++++++++++----------- 
   sandbox/fmhess/boost/generic_ptr/monitor.hpp          |     8 +-                                      
   sandbox/fmhess/libs/generic_ptr/test/cloning_test.cpp |    81 ++++++++++++----------------            
   3 files changed, 118 insertions(+), 82 deletions(-)
Modified: sandbox/fmhess/boost/generic_ptr/cloning.hpp
==============================================================================
--- sandbox/fmhess/boost/generic_ptr/cloning.hpp	(original)
+++ sandbox/fmhess/boost/generic_ptr/cloning.hpp	2009-08-20 14:51:51 EDT (Thu, 20 Aug 2009)
@@ -15,6 +15,7 @@
 #define BOOST_GENERIC_PTR_CLONING_HPP_INCLUDED
 
 #include <boost/config.hpp>
+#include <boost/aligned_storage.hpp>
 #include <boost/generic_ptr/detail/util.hpp>
 #include <boost/generic_ptr/pointer_cast.hpp>
 #include <boost/generic_ptr/pointer_traits.hpp>
@@ -23,8 +24,10 @@
 #include <boost/noncopyable.hpp>
 #include <boost/ptr_container/clone_allocator.hpp>
 #include <boost/scoped_ptr.hpp>
+#include <boost/type_traits/alignment_of.hpp>
 #include <boost/type_traits/is_convertible.hpp>
 #include <boost/type_traits/remove_const.hpp>
+#include <boost/utility/addressof.hpp>
 #include <boost/utility/enable_if.hpp>
 #include <boost/utility/swap.hpp>
 
@@ -33,16 +36,45 @@
   namespace generic_ptr
   {
     template<typename T>
-    T* new_clone(T *p)
+    T* construct_clone(void *location, T *p)
     {
       if(p == 0) return 0;
-      using boost::new_clone;
-      return new_clone(*p);
+      // based on boost::new_clone
+      T* result = new(location) T(*p);
+      BOOST_ASSERT
+      (
+        typeid(*p) == typeid(*result) &&
+        "Default construct_clone() sliced object!"
+      );
+      return result;
     }
     template<typename GenericPointer>
-    GenericPointer new_clone(const GenericPointer &p, typename pointer_traits<GenericPointer>::value_type * = 0)
+    GenericPointer construct_clone
+    (
+      void *location,
+      const GenericPointer &p,
+      typename pointer_traits<GenericPointer>::value_type * = 0
+    )
     {
-      return GenericPointer(new_clone(get_pointer(p)));
+      return GenericPointer(construct_clone(location, get_pointer(p)));
+    }
+    template<typename T>
+    void destroy_clone(T *p)
+    {
+      if(p == 0) return;
+      // make sure type is complete: based on boost::checked_delete
+      typedef char type_must_be_complete[ sizeof(T)? 1: -1 ];
+      (void) sizeof(type_must_be_complete);
+      p->~T();
+    }
+    template<typename GenericPointer>
+    void destroy_clone
+    (
+      const GenericPointer &p,
+      typename pointer_traits<GenericPointer>::value_type * = 0
+    )
+    {
+      return destroy_clone(get_pointer(p));
     }
 
     namespace detail
@@ -56,19 +88,21 @@
         virtual clone_factory_impl_base* make_clone() = 0;
       };
 
-      template<typename GenericPointer, typename Deleter, typename Cloner>
-      class clone_factory_pdc_impl: public
+      template<typename GenericPointer, typename Cloner>
+      class clone_factory_impl: public
         clone_factory_impl_base
         <
           typename rebind<GenericPointer, void>::other
         >
       {
       public:
-        clone_factory_pdc_impl(GenericPointer p, Deleter d, Cloner c): px(p), deleter(d), cloner(c)
+        clone_factory_impl(GenericPointer p, Cloner c):
+          cloner(c),
+          px(cloner.allocate_clone(p))
         {}
-        ~clone_factory_pdc_impl()
+        ~clone_factory_impl()
         {
-          deleter(px);
+          cloner.deallocate_clone(px);
         }
         virtual typename rebind<GenericPointer, void>::other get_pointer()
         {
@@ -80,14 +114,13 @@
               >::type
             >(px);
         }
-        virtual clone_factory_pdc_impl* make_clone()
+        virtual clone_factory_impl* make_clone()
         {
-          return new clone_factory_pdc_impl(cloner(px), deleter, cloner);
+          return new clone_factory_impl(px, cloner);
         }
       private:
-        GenericPointer px;
-        Deleter deleter;
         Cloner cloner;
+        GenericPointer px;
       };
 
       template<typename GenericVoidPointer>
@@ -96,8 +129,8 @@
       public:
         clone_factory(): _impl()
         {}
-        template<typename T, typename Deleter, typename Cloner>
-        clone_factory(T p, Deleter d, Cloner c): _impl(new clone_factory_pdc_impl<T, Deleter, Cloner>(p, d, c))
+        template<typename T, typename Cloner>
+        clone_factory(T p, Cloner c): _impl(new clone_factory_impl<T, Cloner>(p, c))
         {}
         clone_factory(const clone_factory &other): _impl(other._impl->make_clone())
         {}
@@ -128,25 +161,40 @@
       }
     }
 
-    class default_cloning_deleter
+    template<typename T>
+    class default_cloner
     {
     public:
+      default_cloner(): _allocated(false)
+      {}
+      default_cloner(const default_cloner &): _allocated(false)
+      {}
+      default_cloner & operator=(const default_cloner &)
+      {}
       template<typename GenericPointer>
-      void operator()(const GenericPointer &p) const
+      GenericPointer allocate_clone(const GenericPointer & p)
       {
-        delete_clone(get_plain_old_pointer(p));
+        BOOST_ASSERT(_allocated == false);
+        using boost::generic_ptr::construct_clone;
+        GenericPointer result(construct_clone(storage(), p));
+        _allocated = true;
+        return result;
       }
-    };
-
-    class default_cloner
-    {
-    public:
       template<typename GenericPointer>
-      GenericPointer operator()(const GenericPointer & p) const
+      void deallocate_clone(const GenericPointer & p)
       {
-        if(get_plain_old_pointer(p) == 0) return p;
-        return new_clone(p);
+        typename pointer_traits<GenericPointer>::value_type *pop = get_plain_old_pointer(p);
+        if(pop == 0) return;
+        BOOST_ASSERT(pop == storage());
+        BOOST_ASSERT(_allocated);
+        _allocated = false;
+        using boost::generic_ptr::destroy_clone;
+        destroy_clone(p);
       }
+    private:
+      void * storage() {return boost::addressof(_storage);}
+      boost::aligned_storage<sizeof(T), boost::alignment_of<T>::value> _storage;
+      bool _allocated;
     };
 
     template<typename T>
@@ -180,8 +228,7 @@
         _clone_factory
         (
           typename generic_ptr::rebind<T, typename pointer_traits<U>::value_type>::other(p),
-          default_cloning_deleter(),
-          default_cloner()
+          default_cloner<typename pointer_traits<U>::value_type>()
         ),
         px
         (
@@ -201,8 +248,7 @@
         _clone_factory
         (
           typename generic_ptr::rebind<T, typename pointer_traits<U>::value_type>::other(p),
-          default_cloning_deleter(),
-          default_cloner()
+          default_cloner<typename pointer_traits<U>::value_type>()
         ),
         px
         (
@@ -223,7 +269,7 @@
         (
           typename generic_ptr::rebind<T, typename pointer_traits<U>::value_type>::other(p),
           d,
-          default_cloner()
+          default_cloner<typename pointer_traits<U>::value_type>()
         ),
         px
         (
@@ -238,7 +284,6 @@
         _clone_factory
         (
           typename generic_ptr::rebind<T, typename pointer_traits<U>::value_type>::other(p),
-          d,
           c
         ),
         px
Modified: sandbox/fmhess/boost/generic_ptr/monitor.hpp
==============================================================================
--- sandbox/fmhess/boost/generic_ptr/monitor.hpp	(original)
+++ sandbox/fmhess/boost/generic_ptr/monitor.hpp	2009-08-20 14:51:51 EDT (Thu, 20 Aug 2009)
@@ -247,14 +247,14 @@
       return std::less<typename monitor<T, Mutex>::pointer>()(a.get(), b.get());
     }
 
-    // new_clone overload for safe (mutex locked) use with generic_ptr::cloning
+    // construct_clone overload for safe (mutex locked) use with generic_ptr::cloning
     template<typename GenericPointer, typename Mutex>
-    monitor<GenericPointer, Mutex> new_clone(const monitor<GenericPointer, Mutex> &p)
+    monitor<GenericPointer, Mutex> construct_clone(void *location, const monitor<GenericPointer, Mutex> &p)
     {
       if(get_plain_old_pointer(p) == 0) return p;
       monitor_unique_lock<monitor<GenericPointer, Mutex> > lock(p);
-      using boost::generic_ptr::new_clone;
-      return monitor<GenericPointer, Mutex>(new_clone(p.get()));
+      using boost::generic_ptr::construct_clone;
+      return monitor<GenericPointer, Mutex>(construct_clone(location, p.get()));
     }
   } // namespace generic_ptr
 } // namespace boost
Modified: sandbox/fmhess/libs/generic_ptr/test/cloning_test.cpp
==============================================================================
--- sandbox/fmhess/libs/generic_ptr/test/cloning_test.cpp	(original)
+++ sandbox/fmhess/libs/generic_ptr/test/cloning_test.cpp	2009-08-20 14:51:51 EDT (Thu, 20 Aug 2009)
@@ -43,54 +43,61 @@
 void clone_test()
 {
   BOOST_TEST(X::instances == 0);
-  boost::generic_ptr::cloning<X*> cp(new X());
+  X obj;
   BOOST_TEST(X::instances == 1);
-  boost::generic_ptr::cloning<X*> cp2(cp);
+  boost::generic_ptr::cloning<X*> cp(&obj);
   BOOST_TEST(X::instances == 2);
+  boost::generic_ptr::cloning<X*> cp2(cp);
+  BOOST_TEST(X::instances == 3);
   BOOST_TEST(cp != cp2);
   boost::generic_ptr::cloning<const X*> cp3;
-  BOOST_TEST(X::instances == 2);
-  cp3 = cp2;
   BOOST_TEST(X::instances == 3);
+  cp3 = cp2;
+  BOOST_TEST(X::instances == 4);
   BOOST_TEST(cp3->num_instances() == X::instances);
   BOOST_TEST(cp2 != cp3);
 
-  const X* p_to_const = new X();
-  cp3.reset(p_to_const);
-  BOOST_TEST(X::instances == 3);
+  {
+    const X const_obj;
+    cp3.reset(&const_obj);
+  }
+  BOOST_TEST(X::instances == 4);
 }
 
 void move_test()
 {
 #ifndef BOOST_NO_RVALUE_REFERENCES
   BOOST_TEST(X::instances == 0);
-  X * plain_x = new X();
-  boost::generic_ptr::cloning<X*> cp(plain_x);
+  X plain_x;
   BOOST_TEST(X::instances == 1);
-  BOOST_TEST(cp == plain_x);
+  boost::generic_ptr::cloning<X*> cp(&plain_x);
+  X* original_p = cp.get();
+  BOOST_TEST(X::instances == 2);
   boost::generic_ptr::cloning<X*> cp2(std::move(cp));
-  BOOST_TEST(X::instances == 1);
+  BOOST_TEST(X::instances == 2);
   BOOST_TEST(cp.get() == 0);
-  BOOST_TEST(cp2 == plain_x);
+  BOOST_TEST(cp2 == original_p);
   boost::generic_ptr::cloning<X*> cp3;
   cp3 = std::move(cp2);
-  BOOST_TEST(X::instances == 1);
-  BOOST_TEST(cp3 == plain_x);
+  BOOST_TEST(X::instances == 2);
+  BOOST_TEST(cp3 == original_p);
 #endif // BOOST_NO_RVALUE_REFERENCES
 }
 
 void no_slice_test()
 {
   BOOST_TEST(X::instances == 0);
-  boost::generic_ptr::cloning<X*> cp(new X());
+  X obj;
   BOOST_TEST(X::instances == 1);
-  boost::generic_ptr::cloning<X_base*> cp2(cp);
+  boost::generic_ptr::cloning<X*> cp(&obj);
   BOOST_TEST(X::instances == 2);
+  boost::generic_ptr::cloning<X_base*> cp2(cp);
+  BOOST_TEST(X::instances == 3);
   BOOST_TEST(cp != cp2);
   boost::generic_ptr::cloning<X_base*> cp3;
-  BOOST_TEST(X::instances == 2);
-  cp3 = cp;
   BOOST_TEST(X::instances == 3);
+  cp3 = cp;
+  BOOST_TEST(X::instances == 4);
   BOOST_TEST(cp3->f() == 0);
   BOOST_TEST(cp != cp3);
 }
@@ -98,46 +105,31 @@
 void cast_test()
 {
   BOOST_TEST(X::instances == 0);
-  boost::generic_ptr::cloning<X_base*> cp(new X());
+  X obj;
   BOOST_TEST(X::instances == 1);
-  boost::generic_ptr::cloning<X*> cp2 = boost::generic_ptr::static_pointer_cast<X>(cp);
+  boost::generic_ptr::cloning<X_base*> cp(&obj);
   BOOST_TEST(X::instances == 2);
+  boost::generic_ptr::cloning<X*> cp2 = boost::generic_ptr::static_pointer_cast<X>(cp);
+  BOOST_TEST(X::instances == 3);
   BOOST_TEST(cp != cp2);
   boost::generic_ptr::cloning<X_base*> cp3(boost::generic_ptr::static_pointer_cast<X_base>(cp2));
-  BOOST_TEST(X::instances == 3);
+  BOOST_TEST(X::instances == 4);
   BOOST_TEST(cp2 != cp3);
 }
 
-void deleter_test()
-{
-  BOOST_TEST(X::instances == 0);
-  X *x0 = new X();
-  X *x1 = 0;
-  {
-    boost::generic_ptr::cloning<X*> cp0(x0, boost::generic_ptr::null_deleter());
-    BOOST_TEST(X::instances == 1);
-    {
-      boost::generic_ptr::cloning<X*> cp1(cp0);
-      BOOST_TEST(X::instances == 2);
-      x1 = get_plain_old_pointer(cp1);
-    }
-    BOOST_TEST(X::instances == 2);
-  }
-  BOOST_TEST(X::instances == 2);
-  using boost::delete_clone;
-  delete_clone(x0);
-  delete_clone(x1);
-  BOOST_TEST(X::instances == 0);
-}
-
 class null_cloner
 {
 public:
   template<typename GenericPointer>
-  GenericPointer operator()(const GenericPointer &p)
+  GenericPointer allocate_clone(const GenericPointer &p)
   {
     return p;
   }
+  template<typename GenericPointer>
+  void deallocate_clone(const GenericPointer &p)
+  {
+    return;
+  }
 };
 
 void custom_cloner_test()
@@ -162,7 +154,6 @@
   move_test();
   no_slice_test();
   cast_test();
-  deleter_test();
   custom_cloner_test();
   return boost::report_errors();
 }