diff --git a/include/boost/smart_ptr/detail/array_allocator.hpp b/include/boost/smart_ptr/detail/array_allocator.hpp index 8b682eb..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 @@ -54,8 +55,10 @@ namespace boost { typedef typename std::allocator_traits:: 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: @@ -84,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 @@ -127,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); } @@ -135,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 @@ -145,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 @@ -170,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 529c112..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,53 +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 TA; typedef typename std::allocator_traits:: template rebind_traits TT; +#else + typedef typename A:: + template rebind::other TA; #endif void destroy(type*, std::size_t, boost::true_type) { @@ -101,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 @@ -116,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(); @@ -130,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(); @@ -143,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(); @@ -164,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]); @@ -186,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 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