From 2346941b153ba46cb4352eb256b05e49986ed6d3 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Fri, 30 Nov 2012 17:29:36 +0000 Subject: [PATCH] Merged revision(s) 81608-81610 from trunk: Optimization: Add specializations of make_array_helper, allocate_array_helper, and array_deleter for fixed size arrays to avoid storing size. ........ Consistent formatting across overloads of make_shared and allocate_shared (array forms). ........ More consistency in type parameters in helper details of allocate_shared and make_shared. ........ [SVN r81635] --- .../boost/smart_ptr/allocate_shared_array.hpp | 76 +++++++------- .../detail/allocate_array_helper.hpp | 93 +++++++++++++++--- .../boost/smart_ptr/detail/array_deleter.hpp | 67 ++++++++++++- .../smart_ptr/detail/make_array_helper.hpp | 86 ++++++++++++++-- include/boost/smart_ptr/make_shared_array.hpp | 98 +++++++++---------- 5 files changed, 311 insertions(+), 109 deletions(-) diff --git a/include/boost/smart_ptr/allocate_shared_array.hpp b/include/boost/smart_ptr/allocate_shared_array.hpp index e6fa081..4a7de24 100644 --- a/include/boost/smart_ptr/allocate_shared_array.hpp +++ b/include/boost/smart_ptr/allocate_shared_array.hpp @@ -28,12 +28,12 @@ namespace boost { T1* p1 = 0; T2* p2 = 0; std::size_t n1 = size * boost::detail::array_total::size; - boost::detail::allocate_array_helper a1(allocator, n1, &p2); - boost::detail::array_deleter d1; + boost::detail::allocate_array_helper a1(allocator, n1, &p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; + boost::detail::array_deleter* d2; p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); + d2 = get_deleter >(s1); d2->construct(p2, n1); return boost::shared_ptr(s1, p1); } @@ -46,12 +46,12 @@ namespace boost { T1* p1 = 0; T2* p2 = 0; std::size_t n1 = size * boost::detail::array_total::size; - boost::detail::allocate_array_helper a1(allocator, n1, &p2); - boost::detail::array_deleter d1; + boost::detail::allocate_array_helper a1(allocator, n1, &p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; + boost::detail::array_deleter* d2; p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); + d2 = get_deleter >(s1); d2->construct(p2, n1, boost::detail::sp_forward(args)...); return boost::shared_ptr(s1, p1); } @@ -62,14 +62,14 @@ namespace boost { typedef typename boost::detail::array_base::type T2; T1* p1 = 0; T2* p2 = 0; - std::size_t n1 = boost::detail::array_total::size; - boost::detail::allocate_array_helper a1(allocator, n1, &p2); - boost::detail::array_deleter d1; + enum { N = boost::detail::array_total::size }; + boost::detail::allocate_array_helper a1(allocator, &p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; + boost::detail::array_deleter* d2; p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); - d2->construct(p2, n1, boost::detail::sp_forward(args)...); + d2 = get_deleter >(s1); + d2->construct(p2, boost::detail::sp_forward(args)...); return boost::shared_ptr(s1, p1); } #endif @@ -85,13 +85,13 @@ namespace boost { T2* p2 = 0; T3* p3 = 0; std::size_t n1 = list.size() * boost::detail::array_total::size; - boost::detail::allocate_array_helper a1(allocator, n1, &p2); - boost::detail::array_deleter d1; + boost::detail::allocate_array_helper a1(allocator, n1, &p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; + boost::detail::array_deleter* d2; p3 = reinterpret_cast(list.begin()); p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); + d2 = get_deleter >(s1); d2->construct_list(p2, n1, p3); return boost::shared_ptr(s1, p1); } @@ -106,15 +106,15 @@ namespace boost { T1* p1 = 0; T2* p2 = 0; T3* p3 = 0; - std::size_t n1 = boost::detail::array_total::size; - boost::detail::allocate_array_helper a1(allocator, n1, &p2); - boost::detail::array_deleter d1; + enum { N = boost::detail::array_total::size }; + boost::detail::allocate_array_helper a1(allocator, &p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; + boost::detail::array_deleter* d2; p3 = reinterpret_cast(list.begin()); p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); - d2->construct_list(p2, n1, p3); + d2 = get_deleter >(s1); + d2->construct_list(p2, p3); return boost::shared_ptr(s1, p1); } template @@ -127,16 +127,16 @@ namespace boost { T1* p1 = 0; T2* p2 = 0; T3* p3 = 0; - std::size_t n0 = boost::detail::array_total::size; - std::size_t n1 = n0 * list.size(); - boost::detail::allocate_array_helper a1(allocator, n1, &p2); - boost::detail::array_deleter d1; + enum { M = boost::detail::array_total::size }; + std::size_t n1 = M * list.size(); + boost::detail::allocate_array_helper a1(allocator, n1, &p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; + boost::detail::array_deleter* d2; p3 = reinterpret_cast(list.begin()); p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); - d2->construct_list(p2, n1, p3, n0); + d2 = get_deleter >(s1); + d2->construct_list(p2, n1, p3, M); return boost::shared_ptr(s1, p1); } template @@ -150,16 +150,16 @@ namespace boost { T1* p1 = 0; T2* p2 = 0; T3* p3 = 0; - std::size_t n0 = boost::detail::array_total::size; - std::size_t n1 = boost::detail::array_total::size; - boost::detail::allocate_array_helper a1(allocator, n1, &p2); - boost::detail::array_deleter d1; + enum { M = boost::detail::array_total::size }; + enum { N = boost::detail::array_total::size }; + boost::detail::allocate_array_helper a1(allocator, &p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; + boost::detail::array_deleter* d2; p3 = reinterpret_cast(list.begin()); p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); - d2->construct_list(p2, n1, p3, n0); + d2 = get_deleter >(s1); + d2->construct_list(p2, p3, M); return boost::shared_ptr(s1, p1); } #endif diff --git a/include/boost/smart_ptr/detail/allocate_array_helper.hpp b/include/boost/smart_ptr/detail/allocate_array_helper.hpp index dee34ad..f7c64fe 100644 --- a/include/boost/smart_ptr/detail/allocate_array_helper.hpp +++ b/include/boost/smart_ptr/detail/allocate_array_helper.hpp @@ -13,8 +13,10 @@ namespace boost { namespace detail { - template - class allocate_array_helper { + template + class allocate_array_helper; + template + class allocate_array_helper { template friend class allocate_array_helper; typedef typename A::template rebind ::other A2; @@ -29,20 +31,15 @@ namespace boost { typedef typename A2::difference_type difference_type; template struct rebind { - typedef allocate_array_helper other; + typedef allocate_array_helper other; }; allocate_array_helper(const A& allocator, std::size_t size, T** data) : allocator(allocator), size(sizeof(T) * size), data(data) { } - allocate_array_helper(const allocate_array_helper& other) - : allocator(other.allocator), - size(other.size), - data(other.data) { - } template - allocate_array_helper(const allocate_array_helper& other) + allocate_array_helper(const allocate_array_helper& other) : allocator(other.allocator), size(other.size), data(other.data) { @@ -80,11 +77,11 @@ namespace boost { allocator.destroy(memory); } template - bool operator==(const allocate_array_helper& other) const { + bool operator==(const allocate_array_helper& other) const { return allocator == other.allocator; } template - bool operator!=(const allocate_array_helper& other) const { + bool operator!=(const allocate_array_helper& other) const { return !(*this == other); } private: @@ -92,6 +89,80 @@ namespace boost { std::size_t size; T** data; }; + template + class allocate_array_helper { + template + friend class allocate_array_helper; + typedef typename A::template rebind ::other A2; + typedef typename A::template rebind::other A3; + public: + typedef typename A2::value_type value_type; + typedef typename A2::pointer pointer; + typedef typename A2::const_pointer const_pointer; + typedef typename A2::reference reference; + typedef typename A2::const_reference const_reference; + typedef typename A2::size_type size_type; + typedef typename A2::difference_type difference_type; + template + struct rebind { + typedef allocate_array_helper other; + }; + allocate_array_helper(const A& allocator, T** data) + : allocator(allocator), + data(data) { + } + template + allocate_array_helper(const allocate_array_helper& other) + : allocator(other.allocator), + data(other.data) { + } + pointer address(reference value) const { + return allocator.address(value); + } + const_pointer address(const_reference value) const { + return allocator.address(value); + } + size_type max_size() const { + return allocator.max_size(); + } + pointer allocate(size_type count, const void* value = 0) { + std::size_t a1 = boost::alignment_of::value; + std::size_t n1 = count * sizeof(Y) + a1 - 1; + char* p1 = A3(allocator).allocate(n1 + N1, value); + char* p2 = p1 + n1; + while (std::size_t(p2) % a1 != 0) { + p2--; + } + *data = reinterpret_cast(p2); + return reinterpret_cast(p1); + } + void deallocate(pointer memory, size_type count) { + std::size_t a1 = boost::alignment_of::value; + std::size_t n1 = count * sizeof(Y) + a1 - 1; + char* p1 = reinterpret_cast(memory); + A3(allocator).deallocate(p1, n1 + N1); + } + void construct(pointer memory, const Y& value) { + allocator.construct(memory, value); + } + void destroy(pointer memory) { + allocator.destroy(memory); + } + template + bool operator==(const allocate_array_helper& other) const { + return allocator == other.allocator; + } + template + bool operator!=(const allocate_array_helper& other) const { + return !(*this == other); + } + private: + enum { + N1 = N * sizeof(T) + }; + A2 allocator; + T** data; + }; } } diff --git a/include/boost/smart_ptr/detail/array_deleter.hpp b/include/boost/smart_ptr/detail/array_deleter.hpp index 273dcac..b43f5fa 100644 --- a/include/boost/smart_ptr/detail/array_deleter.hpp +++ b/include/boost/smart_ptr/detail/array_deleter.hpp @@ -15,7 +15,9 @@ namespace boost { namespace detail { template - class array_deleter { + class array_deleter; + template + class array_deleter { public: array_deleter() : size(0) { @@ -70,6 +72,69 @@ namespace boost { std::size_t size; T* object; }; + template + class array_deleter { + public: + array_deleter() + : object(0) { + } + ~array_deleter() { + destroy(); + } + void construct(T* memory) { + object = memory; + for (std::size_t i = 0; i < N; i++) { + void* p1 = object + i; + ::new(p1) T(); + } + } +#if defined(BOOST_HAS_VARIADIC_TMPL) && defined(BOOST_HAS_RVALUE_REFS) + template + void construct(T* memory, Args&&... args) { + object = memory; + for (std::size_t i = 0; i < N; i++) { + void* p1 = object + i; + ::new(p1) T(args...); + } + } +#endif +#if !defined(BOOST_NO_CXX11_HDR_INITIALIZER_LIST) + void construct_list(T* memory, const T* list) { + object = memory; + for (std::size_t i = 0; i < N; i++) { + void* p1 = object + i; + ::new(p1) T(list[i]); + } + } + void construct_list(T* memory, const T* list, std::size_t n) { + object = memory; + for (std::size_t i = 0; i < N; i++) { + void* p1 = object + i; + ::new(p1) T(list[i % n]); + } + } +#endif + void construct_noinit(T* memory) { + object = memory; + for (std::size_t i = 0; i < N; i++) { + void* p1 = object + i; + ::new(p1) T; + } + } + void operator()(const void*) { + destroy(); + } + private: + void destroy() { + if (object) { + for (std::size_t i = N; i > 0; ) { + object[--i].~T(); + } + object = 0; + } + } + T* object; + }; } } diff --git a/include/boost/smart_ptr/detail/make_array_helper.hpp b/include/boost/smart_ptr/detail/make_array_helper.hpp index 4d92be3..38c9dc9 100644 --- a/include/boost/smart_ptr/detail/make_array_helper.hpp +++ b/include/boost/smart_ptr/detail/make_array_helper.hpp @@ -13,8 +13,10 @@ namespace boost { namespace detail { - template - class make_array_helper { + template + class make_array_helper; + template + class make_array_helper { template friend class make_array_helper; public: @@ -27,18 +29,14 @@ namespace boost { typedef ptrdiff_t difference_type; template struct rebind { - typedef make_array_helper other; + typedef make_array_helper other; }; make_array_helper(std::size_t size, T** data) : size(sizeof(T) * size), data(data) { } - make_array_helper(const make_array_helper& other) - : size(other.size), - data(other.data) { - } template - make_array_helper(const make_array_helper& other) + make_array_helper(const make_array_helper& other) : size(other.size), data(other.data) { } @@ -74,17 +72,85 @@ namespace boost { memory->~Y(); } template - bool operator==(const make_array_helper& other) const { + bool operator==(const make_array_helper& other) const { return true; } template - bool operator!=(const make_array_helper& other) const { + bool operator!=(const make_array_helper& other) const { return !(*this == other); } private: std::size_t size; T** data; }; + template + class make_array_helper { + template + friend class make_array_helper; + public: + typedef Y value_type; + typedef Y* pointer; + typedef const Y* const_pointer; + typedef Y& reference; + typedef const Y& const_reference; + typedef std::size_t size_type; + typedef ptrdiff_t difference_type; + template + struct rebind { + typedef make_array_helper other; + }; + make_array_helper(T** data) + : data(data) { + } + template + make_array_helper(const make_array_helper& other) + : data(other.data) { + } + pointer address(reference value) const { + return &value; + } + const_pointer address(const_reference value) const { + return &value; + } + size_type max_size() const { + return static_cast(-1) / sizeof(Y); + } + pointer allocate(size_type count, const void* = 0) { + std::size_t a1 = boost::alignment_of::value; + std::size_t n1 = count * sizeof(Y) + a1 - 1; + void* p1 = ::operator new(n1 + N1); + char* p2 = static_cast(p1) + n1; + while (std::size_t(p2) % a1 != 0) { + p2--; + } + *data = reinterpret_cast(p2); + return reinterpret_cast(p1); + } + void deallocate(pointer memory, size_type) { + void* p1 = memory; + ::operator delete(p1); + } + void construct(pointer memory, const Y& value) { + void* p1 = memory; + ::new(p1) Y(value); + } + void destroy(pointer memory) { + memory->~Y(); + } + template + bool operator==(const make_array_helper& other) const { + return true; + } + template + bool operator!=(const make_array_helper& other) const { + return !(*this == other); + } + private: + enum { + N1 = N * sizeof(T) + }; + T** data; + }; } } diff --git a/include/boost/smart_ptr/make_shared_array.hpp b/include/boost/smart_ptr/make_shared_array.hpp index 36e0ddd..d1eeac7 100644 --- a/include/boost/smart_ptr/make_shared_array.hpp +++ b/include/boost/smart_ptr/make_shared_array.hpp @@ -28,12 +28,12 @@ namespace boost { T1* p1 = 0; T2* p2 = 0; std::size_t n1 = size * boost::detail::array_total::size; - boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1; + boost::detail::make_array_helper a1(n1, &p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; + boost::detail::array_deleter* d2; p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); + d2 = get_deleter >(s1); d2->construct(p2, n1); return boost::shared_ptr(s1, p1); } @@ -46,12 +46,12 @@ namespace boost { T1* p1 = 0; T2* p2 = 0; std::size_t n1 = size * boost::detail::array_total::size; - boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1; + boost::detail::make_array_helper a1(n1, &p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; + boost::detail::array_deleter* d2; p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); + d2 = get_deleter >(s1); d2->construct(p2, n1, boost::detail::sp_forward(args)...); return boost::shared_ptr(s1, p1); } @@ -62,14 +62,14 @@ namespace boost { typedef typename boost::detail::array_base::type T2; T1* p1 = 0; T2* p2 = 0; - std::size_t n1 = boost::detail::array_total::size; - boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1; + enum { N = boost::detail::array_total::size }; + boost::detail::make_array_helper a1(&p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; + boost::detail::array_deleter* d2; p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); - d2->construct(p2, n1, boost::detail::sp_forward(args)...); + d2 = get_deleter >(s1); + d2->construct(p2, boost::detail::sp_forward(args)...); return boost::shared_ptr(s1, p1); } #endif @@ -84,13 +84,13 @@ namespace boost { T2* p2 = 0; T3* p3 = 0; std::size_t n1 = list.size() * boost::detail::array_total::size; - boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1; + boost::detail::make_array_helper a1(n1, &p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; + boost::detail::array_deleter* d2; p3 = reinterpret_cast(list.begin()); p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); + d2 = get_deleter >(s1); d2->construct_list(p2, n1, p3); return boost::shared_ptr(s1, p1); } @@ -104,15 +104,15 @@ namespace boost { T1* p1 = 0; T2* p2 = 0; T3* p3 = 0; - std::size_t n1 = boost::detail::array_total::size; - boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1; + enum { N = boost::detail::array_total::size }; + boost::detail::make_array_helper a1(&p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; + boost::detail::array_deleter* d2; p3 = reinterpret_cast(list.begin()); p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); - d2->construct_list(p2, n1, p3); + d2 = get_deleter >(s1); + d2->construct_list(p2, p3); return boost::shared_ptr(s1, p1); } template @@ -125,16 +125,16 @@ namespace boost { T1* p1 = 0; T2* p2 = 0; T3* p3 = 0; - std::size_t n0 = boost::detail::array_total::size; - std::size_t n1 = n0 * size; - boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1; + enum { M = boost::detail::array_total::size }; + std::size_t n1 = M * size; + boost::detail::make_array_helper a1(n1, &p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; + boost::detail::array_deleter* d2; p3 = reinterpret_cast(list.begin()); p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); - d2->construct_list(p2, n1, p3, n0); + d2 = get_deleter >(s1); + d2->construct_list(p2, n1, p3, M); return boost::shared_ptr(s1, p1); } template @@ -147,16 +147,16 @@ namespace boost { T1* p1 = 0; T2* p2 = 0; T3* p3 = 0; - std::size_t n0 = boost::detail::array_total::size; - std::size_t n1 = boost::detail::array_total::size; - boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1; + enum { M = boost::detail::array_total::size }; + enum { N = boost::detail::array_total::size }; + boost::detail::make_array_helper a1(&p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; + boost::detail::array_deleter* d2; p3 = reinterpret_cast(list.begin()); p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); - d2->construct_list(p2, n1, p3, n0); + d2 = get_deleter >(s1); + d2->construct_list(p2, p3, M); return boost::shared_ptr(s1, p1); } #endif @@ -168,12 +168,12 @@ namespace boost { T1* p1 = 0; T2* p2 = 0; std::size_t n1 = size * boost::detail::array_total::size; - boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1; + boost::detail::make_array_helper a1(n1, &p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; + boost::detail::array_deleter* d2; p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); + d2 = get_deleter >(s1); d2->construct_noinit(p2, n1); return boost::shared_ptr(s1, p1); } @@ -184,14 +184,14 @@ namespace boost { typedef typename boost::detail::array_base::type T2; T1* p1 = 0; T2* p2 = 0; - std::size_t n1 = boost::detail::array_total::size; - boost::detail::make_array_helper a1(n1, &p2); - boost::detail::array_deleter d1; + enum { N = boost::detail::array_total::size }; + boost::detail::make_array_helper a1(&p2); + boost::detail::array_deleter d1; boost::shared_ptr s1(p1, d1, a1); - boost::detail::array_deleter* d2; - p1 = reinterpret_cast(p2); - d2 = get_deleter >(s1); - d2->construct_noinit(p2, n1); + boost::detail::array_deleter* d2; + p1 = reinterpret_cast(p2); + d2 = get_deleter >(s1); + d2->construct_noinit(p2); return boost::shared_ptr(s1, p1); } }