|
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