From 51ab46a07dd90af4c3b0f6c8fd9e40a45c7fd9ea Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Tue, 4 Feb 2014 08:43:36 -0800 Subject: [PATCH 1/2] Fix use of rebind_traits and rebind_alloc --- .../smart_ptr/detail/array_allocator.hpp | 56 +++++++++---------- .../boost/smart_ptr/detail/array_deleter.hpp | 56 +++++++------------ include/boost/smart_ptr/detail/as_pair.hpp | 29 ++++++++++ 3 files changed, 76 insertions(+), 65 deletions(-) create mode 100644 include/boost/smart_ptr/detail/as_pair.hpp diff --git a/include/boost/smart_ptr/detail/array_allocator.hpp b/include/boost/smart_ptr/detail/array_allocator.hpp index 3371545..bac8984 100644 --- a/include/boost/smart_ptr/detail/array_allocator.hpp +++ b/include/boost/smart_ptr/detail/array_allocator.hpp @@ -10,6 +10,7 @@ #define BOOST_SMART_PTR_DETAIL_ARRAY_ALLOCATOR_HPP #include +#include #include #if !defined(BOOST_NO_CXX11_ALLOCATOR) #include @@ -46,19 +47,18 @@ namespace boost { #if !defined(BOOST_NO_CXX11_ALLOCATOR) typedef typename std::allocator_traits:: - template rebind_alloc::other YA; - + template rebind_alloc YA; typedef typename std::allocator_traits:: - template rebind_alloc::other CA; - + template rebind_alloc CA; typedef typename std::allocator_traits:: - template rebind_traits::other YT; - + template rebind_traits YT; typedef typename std::allocator_traits:: - template rebind_traits::other CT; + template rebind_traits CT; #else - typedef typename A::template rebind::other YA; - typedef typename A::template rebind::other CA; + typedef typename A:: + template rebind::other YA; + typedef typename A:: + template rebind::other CA; #endif public: @@ -87,40 +87,37 @@ namespace boost { typedef as_allocator other; }; - as_allocator(const A& allocator_, type** data_) - : allocator(allocator_), - data(data_) { + as_allocator(const A& allocator, type** data) + : pair(allocator, data) { } - as_allocator(const A& allocator_, std::size_t size_, type** data_) + as_allocator(const A& allocator, std::size_t size_, type** data) : ms_allocator_base(size_), - allocator(allocator_), - data(data_) { + pair(allocator, data) { } template as_allocator(const as_allocator& other) : ms_allocator_base(other), - allocator(other.allocator), - data(other.data) { + pair(other.pair, other.pair.data) { } pointer address(reference value) const { - return allocator.address(value); + return pair.address(value); } const_pointer address(const_reference value) const { - return allocator.address(value); + return pair.address(value); } size_type max_size() const { - return allocator.max_size(); + return pair.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; - CA ca(allocator); + CA ca(pair); #if !defined(BOOST_NO_CXX11_ALLOCATOR) char* p1 = CT::allocate(ca, size + n1, value); #else @@ -130,7 +127,7 @@ namespace boost { while (std::size_t(p2) % a1 != 0) { p2--; } - *data = reinterpret_cast(p2); + *pair.data = reinterpret_cast(p2); return reinterpret_cast(p1); } @@ -138,7 +135,7 @@ namespace boost { std::size_t a1 = boost::alignment_of::value; std::size_t n1 = count * sizeof(Y) + a1 - 1; char* p1 = reinterpret_cast(memory); - CA ca(allocator); + CA ca(pair); #if !defined(BOOST_NO_CXX11_ALLOCATOR) CT::deallocate(ca, p1, size + n1); #else @@ -148,23 +145,23 @@ namespace boost { void construct(pointer memory, const Y& value) { #if !defined(BOOST_NO_CXX11_ALLOCATOR) - YT::construct(allocator, memory, value); + YT::construct(pair, memory, value); #else - allocator.construct(memory, value); + pair.construct(memory, value); #endif } void destroy(pointer memory) { #if !defined(BOOST_NO_CXX11_ALLOCATOR) - YT::destroy(allocator, memory); + YT::destroy(pair, memory); #else - allocator.destroy(memory); + pair.destroy(memory); #endif } template bool operator==(const as_allocator& other) const { - return allocator == other.allocator; + return pair == other.pair; } template @@ -173,8 +170,7 @@ namespace boost { } private: - YA allocator; - type** data; + as_pair pair; }; template diff --git a/include/boost/smart_ptr/detail/array_deleter.hpp b/include/boost/smart_ptr/detail/array_deleter.hpp index 7d99795..b4ed44f 100644 --- a/include/boost/smart_ptr/detail/array_deleter.hpp +++ b/include/boost/smart_ptr/detail/array_deleter.hpp @@ -11,6 +11,7 @@ #include #include +#include #include #include #if !defined(BOOST_NO_CXX11_ALLOCATOR) @@ -46,54 +47,42 @@ namespace boost { public: typedef typename array_inner::type type; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - as_deleter(const A& allocator_) - : allocator(allocator_), - object(0) { + as_deleter(const A& allocator) + : pair(allocator, 0) { } -#else - as_deleter(const A&) - : object(0) { - } -#endif -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - as_deleter(const A& allocator_, std::size_t size_) + as_deleter(const A& allocator, std::size_t size_) : ms_deleter_base(size_), - allocator(allocator_), - object(0) { + pair(allocator, 0) { } -#else - as_deleter(const A&, std::size_t size_) - : ms_deleter_base(size_), - object(0) { - } -#endif void init(type* memory) { value_init(memory); - object = memory; + pair.data = memory; } template void init(type* memory, const type* value) { value_init(memory, value); - object = memory; + pair.data = memory; } void operator()(const void*) { - if (object) { - destroy(object, size); + if (pair.data) { + destroy(pair.data, size); } } private: + #if !defined(BOOST_NO_CXX11_ALLOCATOR) typedef typename std::allocator_traits:: - template rebind_alloc::other TA; - + template rebind_alloc TA; typedef typename std::allocator_traits:: - template rebind_traits::other TT; + template rebind_traits TT; +#else + typedef typename A:: + template rebind::other TA; #endif void destroy(type*, std::size_t, boost::true_type) { @@ -102,7 +91,7 @@ namespace boost { void destroy(type* memory, std::size_t n, boost::false_type) { for (std::size_t i = n; i > 0;) { #if !defined(BOOST_NO_CXX11_ALLOCATOR) - TT::destroy(allocator, &memory[--i]); + TT::destroy(pair, &memory[--i]); #else memory[--i].~type(); #endif @@ -117,7 +106,7 @@ namespace boost { void value_init(type* memory, boost::true_type) { for (std::size_t i = 0; i < size; i++) { #if !defined(BOOST_NO_CXX11_ALLOCATOR) - TT::construct(allocator, memory + i); + TT::construct(pair, memory + i); #else void* p1 = memory + i; ::new(p1) type(); @@ -131,7 +120,7 @@ namespace boost { try { for (; i < size; i++) { #if !defined(BOOST_NO_CXX11_ALLOCATOR) - TT::construct(allocator, memory + i); + TT::construct(pair, memory + i); #else void* p1 = memory + i; ::new(p1) type(); @@ -144,7 +133,7 @@ namespace boost { #else for (std::size_t i = 0; i < size; i++) { #if !defined(BOOST_NO_CXX11_ALLOCATOR) - TT::construct(allocator, memory + i); + TT::construct(pair, memory + i); #else void* p1 = memory + i; ::new(p1) type(); @@ -165,7 +154,7 @@ namespace boost { try { for (; i < size; i++) { #if !defined(BOOST_NO_CXX11_ALLOCATOR) - TT::construct(allocator, memory + i, list[i % N]); + TT::construct(pair, memory + i, list[i % N]); #else void* p1 = memory + i; ::new(p1) type(list[i % N]); @@ -187,10 +176,7 @@ namespace boost { #endif } -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - TA allocator; -#endif - type* object; + as_pair pair; }; template diff --git a/include/boost/smart_ptr/detail/as_pair.hpp b/include/boost/smart_ptr/detail/as_pair.hpp new file mode 100644 index 0000000..829adc0 --- /dev/null +++ b/include/boost/smart_ptr/detail/as_pair.hpp @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#ifndef BOOST_SMART_PTR_DETAIL_AS_PAIR_HPP +#define BOOST_SMART_PTR_DETAIL_AS_PAIR_HPP + +#include + +namespace boost { + namespace detail { + template + struct as_pair + : A { + as_pair(const A& allocator, const T& value) + : A(allocator), + data(value) { + } + + T data; + }; + } +} + +#endif From f27b780724e2af140dae213968ab1c5c9f8f310b Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Tue, 4 Feb 2014 13:16:06 -0800 Subject: [PATCH 2/2] Add unit test for allocate_shared construct case --- test/Jamfile.v2 | 1 + test/allocate_shared_array_construct_test.cpp | 160 ++++++++++++++++++ 2 files changed, 161 insertions(+) create mode 100644 test/allocate_shared_array_construct_test.cpp diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 09263d3..8a74194 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -148,6 +148,7 @@ import testing ; [ run allocate_shared_array_esft_test.cpp ] [ run allocate_shared_array_noinit_test.cpp ] [ run allocate_shared_array_value_test.cpp ] + [ run allocate_shared_array_construct_test.cpp ] [ run make_unique_test.cpp ] [ run make_unique_args_test.cpp ] diff --git a/test/allocate_shared_array_construct_test.cpp b/test/allocate_shared_array_construct_test.cpp new file mode 100644 index 0000000..623aa65 --- /dev/null +++ b/test/allocate_shared_array_construct_test.cpp @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2012-2014 Glen Joseph Fernandes + * glenfe at live dot com + * + * Distributed under the Boost Software License, + * Version 1.0. (See accompanying file LICENSE_1_0.txt + * or copy at http://boost.org/LICENSE_1_0.txt) + */ +#include +#if !defined(BOOST_NO_CXX11_ALLOCATOR) +#include + +template +class creator { +public: + typedef T value_type; + + creator() { + } + + template + creator(const creator&) { + } + + T* allocate(std::size_t size) { + void* p1 = ::operator new(size * sizeof(T)); + return static_cast(p1); + } + + void deallocate(T* memory, std::size_t) { + void* p1 = memory; + ::operator delete(p1); + } + + template + void construct(U* memory, Args&&... args) { + void* p1 = memory; + ::new(p1) U(std::forward(args)...); + } + + template + void destroy(U* memory) { + memory->~U(); + } +}; + +class type { + friend class creator; + +public: + static unsigned int instances; + static type object; + +protected: + explicit type() { + instances++; + } + + type(const type&) { + instances++; + } + + ~type() { + instances--; + } +}; + +unsigned int type::instances; +type type::object; + +int main() { + BOOST_TEST(type::instances == 1); + { + boost::shared_ptr a1 = boost::allocate_shared(creator(), 3); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(type::instances == 4); + a1.reset(); + BOOST_TEST(type::instances == 1); + } + + BOOST_TEST(type::instances == 1); + { + boost::shared_ptr a1 = boost::allocate_shared(creator()); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(type::instances == 4); + a1.reset(); + BOOST_TEST(type::instances == 1); + } + + BOOST_TEST(type::instances == 1); + { + boost::shared_ptr a1 = boost::allocate_shared(creator(), 2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 5); + a1.reset(); + BOOST_TEST(type::instances == 1); + } + + BOOST_TEST(type::instances == 1); + { + boost::shared_ptr a1 = boost::allocate_shared(creator()); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 5); + a1.reset(); + BOOST_TEST(type::instances == 1); + } + + BOOST_TEST(type::instances == 1); + { + boost::shared_ptr a1 = boost::allocate_shared(creator(), 3); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 4); + a1.reset(); + BOOST_TEST(type::instances == 1); + } + + BOOST_TEST(type::instances == 1); + { + boost::shared_ptr a1 = boost::allocate_shared(creator()); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 4); + a1.reset(); + BOOST_TEST(type::instances == 1); + } + + BOOST_TEST(type::instances == 1); + { + boost::shared_ptr a1 = boost::allocate_shared(creator(), 2); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 5); + a1.reset(); + BOOST_TEST(type::instances == 1); + } + + BOOST_TEST(type::instances == 1); + { + boost::shared_ptr a1 = boost::allocate_shared(creator()); + BOOST_TEST(a1.get() != 0); + BOOST_TEST(a1.use_count() == 1); + BOOST_TEST(type::instances == 5); + a1.reset(); + BOOST_TEST(type::instances == 1); + } + + return boost::report_errors(); +} +#else + +int main() { + return 0; +} + +#endif