Boost logo

Boost-Commit :

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();
 }


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