From 970e88897c095782c7c660f43a7c029ccd648d29 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Tue, 28 Feb 2017 01:41:34 -0500 Subject: [PATCH 1/8] Revise make_shared and allocate_shared for arrays --- .../boost/smart_ptr/allocate_shared_array.hpp | 1153 ++++++++++++++--- .../smart_ptr/detail/array_allocator.hpp | 318 ----- .../smart_ptr/detail/array_count_impl.hpp | 67 - .../boost/smart_ptr/detail/array_traits.hpp | 60 - .../boost/smart_ptr/detail/array_utility.hpp | 214 --- .../boost/smart_ptr/detail/sp_if_array.hpp | 34 - include/boost/smart_ptr/make_shared_array.hpp | 204 +-- 7 files changed, 1045 insertions(+), 1005 deletions(-) delete mode 100644 include/boost/smart_ptr/detail/array_allocator.hpp delete mode 100644 include/boost/smart_ptr/detail/array_count_impl.hpp delete mode 100644 include/boost/smart_ptr/detail/array_traits.hpp delete mode 100644 include/boost/smart_ptr/detail/array_utility.hpp delete mode 100644 include/boost/smart_ptr/detail/sp_if_array.hpp diff --git a/include/boost/smart_ptr/allocate_shared_array.hpp b/include/boost/smart_ptr/allocate_shared_array.hpp index 1ae5cc7..75adf27 100644 --- a/include/boost/smart_ptr/allocate_shared_array.hpp +++ b/include/boost/smart_ptr/allocate_shared_array.hpp @@ -1,181 +1,1006 @@ /* - * 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) - */ +Copyright 2012-2017 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ #ifndef BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP #define BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP -#include -#include +#include +#include +#include +#include +#include namespace boost { - template - inline typename boost::detail::sp_if_array::type - allocate_shared(const A& allocator, std::size_t size) { - typedef typename boost::detail::array_inner::type T1; - typedef typename boost::detail::array_base::type T2; - typedef boost::detail::ms_init_tag R1; - typedef boost::detail::as_allocator A1; - typedef boost::detail::ms_in_allocator_tag D1; - std::size_t n1 = size * boost::detail::array_total::size; - T1* p1 = 0; - T2* p2 = 0; - D1 d1; - A1 a1(allocator, size, &p2); - shared_ptr s1(p1, d1, a1); - A1* a2 = static_cast(s1._internal_get_untyped_deleter()); - a2->set(0); +namespace detail { + +template +struct sp_if_array { }; + +template +struct sp_if_array { + typedef boost::shared_ptr type; +}; + +template +struct sp_if_size_array { }; + +template +struct sp_if_size_array { + typedef boost::shared_ptr type; +}; + +template +struct sp_array_element { }; + +template +struct sp_array_element { + typedef T type; +}; + +template +struct sp_array_element { + typedef T type; +}; + +template +struct sp_array_scalar { + typedef T type; +}; + +template +struct sp_array_scalar { + typedef typename sp_array_scalar::type type; +}; + +template +struct sp_array_scalar { + typedef typename sp_array_scalar::type type; +}; + +template +struct sp_array_scalar { + typedef typename sp_array_scalar::type type; +}; + +template +struct sp_array_scalar { + typedef typename sp_array_scalar::type type; +}; + +template +struct sp_array_scalar { + typedef typename sp_array_scalar::type type; +}; + +template +struct sp_array_scalar { + typedef typename sp_array_scalar::type type; +}; + +template +struct sp_array_scalar { + typedef typename sp_array_scalar::type type; +}; + +template +struct sp_array_scalar { + typedef typename sp_array_scalar::type type; +}; + +template +struct sp_array_count { + BOOST_STATIC_CONSTEXPR std::size_t value = 1; +}; + +template +struct sp_array_count { + BOOST_STATIC_CONSTEXPR std::size_t value = N * + sp_array_count::value; +}; + +template +struct sp_array_count { }; + +template +inline D* +sp_get_deleter(const boost::shared_ptr& value) BOOST_NOEXCEPT +{ + return static_cast(value._internal_get_untyped_deleter()); +} + +template +struct sp_array_storage { + union type { + char value[N]; + typename boost::type_with_alignment::type other; + }; +}; + +template +struct sp_max_size { + BOOST_STATIC_CONSTEXPR std::size_t value = N < M ? M : N; +}; + #if !defined(BOOST_NO_CXX11_ALLOCATOR) - boost::detail::as_init(allocator, p2, n1); +template +struct sp_bind_allocator { + typedef typename std::allocator_traits::template + rebind_alloc type; +}; #else - boost::detail::ms_init(p2, n1); +template +struct sp_bind_allocator { + typedef typename A::template rebind::other type; +}; #endif - a2->set(p2); - p1 = reinterpret_cast(p2); - return shared_ptr(s1, p1); - } - template - inline typename boost::detail::sp_if_size_array::type - allocate_shared(const A& allocator) { - typedef typename boost::detail::array_inner::type T1; - typedef typename boost::detail::array_base::type T2; - typedef boost::detail::ms_init_tag R1; - typedef boost::detail::as_allocator A1; - typedef boost::detail::ms_in_allocator_tag D1; - enum { - N = boost::detail::array_total::size - }; - T1* p1 = 0; - T2* p2 = 0; - D1 d1; - A1 a1(allocator, &p2); - shared_ptr s1(p1, d1, a1); - A1* a2 = static_cast(s1._internal_get_untyped_deleter()); - a2->set(0); -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - boost::detail::as_init(allocator, p2, N); -#else - boost::detail::ms_init(p2, N); -#endif - a2->set(p2); - p1 = reinterpret_cast(p2); - return shared_ptr(s1, p1); - } +template +struct sp_enable { }; - template - inline typename boost::detail::sp_if_array::type - allocate_shared(const A& allocator, std::size_t size, - const typename boost::detail::array_inner::type& value) { - typedef typename boost::detail::array_inner::type T1; - typedef typename boost::detail::array_base::type T2; - typedef const T2 T3; - typedef boost::detail::ms_init_tag R1; - typedef boost::detail::as_allocator A1; - typedef boost::detail::ms_in_allocator_tag D1; - enum { - M = boost::detail::array_total::size - }; - std::size_t n1 = M * size; - T1* p1 = 0; - T2* p2 = 0; - T3* p3 = reinterpret_cast(&value); - D1 d1; - A1 a1(allocator, size, &p2); - shared_ptr s1(p1, d1, a1); - A1* a2 = static_cast(s1._internal_get_untyped_deleter()); - a2->set(0); -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - boost::detail::as_init(allocator, p2, n1, p3); -#else - boost::detail::ms_init(p2, n1, p3); -#endif - a2->set(p2); - p1 = reinterpret_cast(p2); - return shared_ptr(s1, p1); - } +template<> +struct sp_enable { + typedef void type; +}; - template - inline typename boost::detail::sp_if_size_array::type - allocate_shared(const A& allocator, - const typename boost::detail::array_inner::type& value) { - typedef typename boost::detail::array_inner::type T1; - typedef typename boost::detail::array_base::type T2; - typedef const T2 T3; - typedef boost::detail::ms_init_tag R1; - typedef boost::detail::as_allocator A1; - typedef boost::detail::ms_in_allocator_tag D1; - enum { - N = boost::detail::array_total::size, - M = boost::detail::array_total::size - }; - T1* p1 = 0; - T2* p2 = 0; - T3* p3 = reinterpret_cast(&value); - D1 d1; - A1 a1(allocator, &p2); - shared_ptr s1(p1, d1, a1); - A1* a2 = static_cast(s1._internal_get_untyped_deleter()); - a2->set(0); -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - boost::detail::as_init(allocator, p2, N, p3); -#else - boost::detail::ms_init(p2, N, p3); -#endif - a2->set(p2); - p1 = reinterpret_cast(p2); - return shared_ptr(s1, p1); - } +template +inline +typename sp_enable::value>::type +sp_array_destroy(T*, std::size_t) BOOST_NOEXCEPT { } - template - inline typename boost::detail::sp_if_array::type - allocate_shared_noinit(const A& allocator, std::size_t size) { - typedef typename boost::detail::array_inner::type T1; - typedef typename boost::detail::array_base::type T2; - typedef boost::detail::ms_noinit_tag R1; - typedef boost::detail::as_allocator A1; - typedef boost::detail::ms_in_allocator_tag D1; - std::size_t n1 = size * boost::detail::array_total::size; - T1* p1 = 0; - T2* p2 = 0; - D1 d1; - A1 a1(allocator, size, &p2); - shared_ptr s1(p1, d1, a1); - A1* a2 = static_cast(s1._internal_get_untyped_deleter()); - a2->set(0); - boost::detail::ms_noinit(p2, n1); - a2->set(p2); - p1 = reinterpret_cast(p2); - return shared_ptr(s1, p1); - } - - template - inline typename boost::detail::sp_if_size_array::type - allocate_shared_noinit(const A& allocator) { - typedef typename boost::detail::array_inner::type T1; - typedef typename boost::detail::array_base::type T2; - typedef boost::detail::ms_noinit_tag R1; - typedef boost::detail::as_allocator A1; - typedef boost::detail::ms_in_allocator_tag D1; - enum { - N = boost::detail::array_total::size - }; - T1* p1 = 0; - T2* p2 = 0; - D1 d1; - A1 a1(allocator, &p2); - shared_ptr s1(p1, d1, a1); - A1* a2 = static_cast(s1._internal_get_untyped_deleter()); - a2->set(0); - boost::detail::ms_noinit(p2, N); - a2->set(p2); - p1 = reinterpret_cast(p2); - return shared_ptr(s1, p1); +template +inline +typename sp_enable::value>::type +sp_array_destroy(T* storage, std::size_t size) +{ + while (size > 0) { + storage[--size].~T(); } } +#if !defined(BOOST_NO_CXX11_ALLOCATOR) +template +inline void +sp_array_destroy(A& allocator, T* storage, std::size_t size) +{ + while (size > 0) { + std::allocator_traits::destroy(allocator, &storage[--size]); + } +} +#endif + +#if !defined(BOOST_NO_EXCEPTIONS) +template +inline +typename sp_enable::value || + boost::has_trivial_destructor::value>::type +sp_array_construct(T* storage, std::size_t size) +{ + for (std::size_t i = 0; i < size; ++i) { + ::new(static_cast(storage + i)) T(); + } +} + +template +inline +typename sp_enable::value && + !boost::has_trivial_destructor::value>::type +sp_array_construct(T* storage, std::size_t size) +{ + std::size_t i = 0; + try { + for (; i < size; ++i) { + ::new(static_cast(storage + i)) T(); + } + } catch (...) { + while (i > 0) { + storage[--i].~T(); + } + throw; + } +} + +template +inline void +sp_array_construct(T* storage, std::size_t size, const T* list, + std::size_t count) +{ + std::size_t i = 0; + try { + for (; i < size; ++i) { + ::new(static_cast(storage + i)) T(list[i % count]); + } + } catch (...) { + while (i > 0) { + storage[--i].~T(); + } + throw; + } +} +#else +template +inline void +sp_array_construct(T* storage, std::size_t size) +{ + for (std::size_t i = 0; i < size; ++i) { + ::new(static_cast(storage + i)) T(); + } +} + +template +inline void +sp_array_construct(T* storage, std::size_t size, const T* list, + std::size_t count) +{ + for (std::size_t i = 0; i < size; ++i) { + ::new(static_cast(storage + i)) T(list[i % count]); + } +} +#endif + +#if !defined(BOOST_NO_CXX11_ALLOCATOR) +#if !defined(BOOST_NO_EXCEPTIONS) +template +inline void +sp_array_construct(A& allocator, T* storage, std::size_t size) +{ + std::size_t i = 0; + try { + for (i = 0; i < size; ++i) { + std::allocator_traits::construct(allocator, storage + i); + } + } catch (...) { + sp_array_destroy(allocator, storage, i); + throw; + } +} + +template +inline void +sp_array_construct(A& allocator, T* storage, std::size_t size, + const T* list, std::size_t count) +{ + std::size_t i = 0; + try { + for (i = 0; i < size; ++i) { + std::allocator_traits::construct(allocator, storage + i, + list[i % count]); + } + } catch (...) { + sp_array_destroy(allocator, storage, i); + throw; + } +} +#else +template +inline void +sp_array_construct(A& allocator, T* storage, std::size_t size) +{ + for (std::size_t i = 0; i < size; ++i) { + std::allocator_traits::construct(allocator, storage + i); + } +} + +template +inline void +sp_array_construct(A& allocator, T* storage, std::size_t size, + const T* list, std::size_t count) +{ + for (std::size_t i = 0; i < size; ++i) { + std::allocator_traits::construct(allocator, storage + i, + list[i % count]); + } +} +#endif +#endif + +template +inline +typename sp_enable::value>::type +sp_array_default(T*, std::size_t) BOOST_NOEXCEPT { } + +#if !defined(BOOST_NO_EXCEPTIONS) +template +inline +typename sp_enable::value && + boost::has_trivial_destructor::value>::type +sp_array_default(T* storage, std::size_t size) +{ + for (std::size_t i = 0; i < size; ++i) { + ::new(static_cast(storage + i)) T; + } +} + +template +inline +typename sp_enable::value && + !boost::has_trivial_destructor::value>::type +sp_array_default(T* storage, std::size_t size) +{ + std::size_t i = 0; + try { + for (; i < size; ++i) { + ::new(static_cast(storage + i)) T; + } + } catch (...) { + while (i > 0) { + storage[--i].~T(); + } + throw; + } +} +#else +template +inline +typename sp_enable::value>::type +sp_array_default(T* storage, std::size_t size) +{ + for (std::size_t i = 0; i < size; ++i) { + ::new(static_cast(storage + i)) T; + } +} +#endif + +template +BOOST_CONSTEXPR inline std::size_t +sp_objects(std::size_t size) BOOST_NOEXCEPT +{ + return size / sizeof(T); +} + +template +BOOST_CONSTEXPR inline std::size_t +sp_align(std::size_t size) BOOST_NOEXCEPT +{ + return (sizeof(T) * size + sizeof(U) - 1) & ~(sizeof(U) - 1); +} + +template +class sp_size_array_deleter { +public: + template + static void operator_fn(U) BOOST_NOEXCEPT { } + + sp_size_array_deleter() BOOST_NOEXCEPT + : enabled_(false) { } + + template + sp_size_array_deleter(const A&) BOOST_NOEXCEPT + : enabled_(false) { } + + sp_size_array_deleter(const sp_size_array_deleter&) BOOST_NOEXCEPT + : enabled_(false) { } + + ~sp_size_array_deleter() { + if (enabled_) { + sp_array_destroy(reinterpret_cast(&storage_), N); + } + } + + template + void operator()(U) { + if (enabled_) { + sp_array_destroy(reinterpret_cast(&storage_), N); + enabled_ = false; + } + } + + void* construct() { + sp_array_construct(reinterpret_cast(&storage_), N); + enabled_ = true; + return &storage_; + } + + void* construct(const T* list, std::size_t count) { + sp_array_construct(reinterpret_cast(&storage_), N, + list, count); + enabled_ = true; + return &storage_; + } + + void* construct_default() { + sp_array_default(reinterpret_cast(&storage_), N); + enabled_ = true; + return &storage_; + } + +private: + bool enabled_; + typename sp_array_storage::value>::type storage_; +}; + +#if !defined(BOOST_NO_CXX11_ALLOCATOR) +template +class sp_size_array_destroyer { +public: + template + static void operator_fn(U) BOOST_NOEXCEPT { } + + template + sp_size_array_destroyer(const U& allocator) BOOST_NOEXCEPT + : allocator_(allocator), + enabled_(false) { } + + sp_size_array_destroyer(const sp_size_array_destroyer& other) + BOOST_NOEXCEPT + : allocator_(other.allocator_), + enabled_(false) { } + + ~sp_size_array_destroyer() { + if (enabled_) { + sp_array_destroy(allocator_, + reinterpret_cast(&storage_), N); + } + } + + template + void operator()(U) { + if (enabled_) { + sp_array_destroy(allocator_, + reinterpret_cast(&storage_), N); + enabled_ = false; + } + } + + void* construct() { + sp_array_construct(allocator_, + reinterpret_cast(&storage_), N); + enabled_ = true; + return &storage_; + } + + void* construct(const T* list, std::size_t count) { + sp_array_construct(allocator_, + reinterpret_cast(&storage_), N, list, count); + enabled_ = true; + return &storage_; + } + + const A& allocator() const BOOST_NOEXCEPT { + return allocator_; + } + +private: + typename sp_array_storage::value>::type storage_; + A allocator_; + bool enabled_; +}; +#endif + +template +class sp_array_deleter { +public: + template + static void operator_fn(U) BOOST_NOEXCEPT { } + + sp_array_deleter(std::size_t size) BOOST_NOEXCEPT + : address_(0), + size_(size) { } + + template + sp_array_deleter(const A& allocator) BOOST_NOEXCEPT + : address_(0), + size_(allocator.size()) { } + + template + sp_array_deleter(const A&, std::size_t size) BOOST_NOEXCEPT + : address_(0), + size_(size) { } + + sp_array_deleter(const sp_array_deleter& other) BOOST_NOEXCEPT + : address_(0), + size_(other.size_) { } + + ~sp_array_deleter() { + if (address_) { + sp_array_destroy(static_cast(address_), size_); + } + } + + template + void operator()(U) { + if (address_) { + sp_array_destroy(static_cast(address_), size_); + address_ = 0; + } + } + + void construct(T* address) { + sp_array_construct(address, size_); + address_ = address; + } + + void construct(T* address, const T* list, std::size_t count) { + sp_array_construct(address, size_, list, count); + address_ = address; + } + + void construct_default(T* address) { + sp_array_default(address, size_); + address_ = address; + } + + std::size_t size() const BOOST_NOEXCEPT { + return size_; + } + +private: + void* address_; + std::size_t size_; +}; + +#if !defined(BOOST_NO_CXX11_ALLOCATOR) +template +class sp_array_destroyer { +public: + template + static void operator_fn(U) BOOST_NOEXCEPT { } + + template + sp_array_destroyer(const U& allocator, std::size_t size) + BOOST_NOEXCEPT + : allocator_(allocator), + size_(size), + address_(0) { } + + template + sp_array_destroyer(const U& allocator) BOOST_NOEXCEPT + : allocator_(allocator.allocator()), + size_(allocator.size()), + address_(0) { } + + sp_array_destroyer(const sp_array_destroyer& other) BOOST_NOEXCEPT + : allocator_(other.allocator_), + size_(other.size_), + address_(0) { } + + ~sp_array_destroyer() { + if (address_) { + sp_array_destroy(allocator_, static_cast(address_), + size_); + } + } + + template + void operator()(U) { + if (address_) { + sp_array_destroy(allocator_, static_cast(address_), + size_); + address_ = 0; + } + } + + void construct(T* address) { + sp_array_construct(allocator_, address, size_); + address_ = address; + } + + void construct(T* address, const T* list, std::size_t count) { + sp_array_construct(allocator_, address, size_, list, count); + address_ = address; + } + + const A& allocator() const BOOST_NOEXCEPT { + return allocator_; + } + + std::size_t size() const BOOST_NOEXCEPT { + return size_; + } + +private: + A allocator_; + std::size_t size_; + void* address_; +}; +#endif + +template +class sp_array_allocator { + template + friend class sp_array_allocator; + +public: + typedef typename A::value_type value_type; + +private: + enum { + alignment = sp_max_size::value, + boost::alignment_of::value>::value + }; + + typedef typename boost::type_with_alignment::type type; + typedef typename sp_bind_allocator::type type_allocator; + +public: + template + struct rebind { + typedef sp_array_allocator::type> other; + }; + + sp_array_allocator(const A& allocator, std::size_t size, + void** result) BOOST_NOEXCEPT + : allocator_(allocator), + size_(size), + result_(result) { } + + sp_array_allocator(const A& allocator, std::size_t size) + BOOST_NOEXCEPT + : allocator_(allocator), + size_(size) { } + + template + sp_array_allocator(const sp_array_allocator& other) + BOOST_NOEXCEPT + : allocator_(other.allocator_), + size_(other.size_), + result_(other.result_) { } + + value_type* allocate(std::size_t count, const void* = 0) { + type_allocator allocator(allocator_); + std::size_t head = sp_align(count); + std::size_t tail = sp_align(size_); + std::size_t size = sp_objects(head + tail); + type* address = allocator.allocate(size); + *result_ = address + sp_objects(head); + return reinterpret_cast(address); + } + + void deallocate(value_type* value, std::size_t count) { + type_allocator allocator(allocator_); + std::size_t head = sp_align(count); + std::size_t tail = sp_align(size_); + std::size_t size = sp_objects(head + tail); + allocator.deallocate(reinterpret_cast(value), size); + } + + const A& allocator() const BOOST_NOEXCEPT { + return allocator_; + } + + std::size_t size() const BOOST_NOEXCEPT { + return size_; + } + +private: + A allocator_; + std::size_t size_; + void** result_; +}; + +template +inline bool +operator==(const sp_array_allocator& first, + const sp_array_allocator& second) BOOST_NOEXCEPT +{ + return first.allocator() == second.allocator() && + first.size() == second.size(); +} + +template +inline bool +operator!=(const sp_array_allocator& first, + const sp_array_allocator& second) BOOST_NOEXCEPT +{ + return !(first == second); +} + +#if !defined(BOOST_NO_CXX11_ALLOCATOR) +template +struct sp_select_size_deleter { + typedef sp_size_array_destroyer::type> type; +}; + +template +struct sp_select_size_deleter, T, N> { + typedef sp_size_array_deleter type; +}; + +template +struct sp_select_deleter { + typedef sp_array_destroyer::type> type; +}; + +template +struct sp_select_deleter, T> { + typedef sp_array_deleter type; +}; +#else +template +struct sp_select_size_deleter { + typedef sp_size_array_deleter type; +}; + +template +struct sp_select_deleter { + typedef sp_array_deleter type; +}; +#endif + +template +class sp_counted_impl_pda, A> + : public sp_counted_base { +public: + typedef sp_size_array_deleter deleter_type; + +private: + typedef sp_counted_impl_pda type; + typedef typename sp_bind_allocator::type deallocator; + +public: + sp_counted_impl_pda(P, const deleter_type&, const A& allocator) + : deleter_(allocator), + allocator_(allocator) { } + + sp_counted_impl_pda(P, const A& allocator) + : deleter_(allocator) { } + + void dispose() { + deleter_(0); + } + + void destroy() { + this->~type(); + deallocator allocator(allocator_); + allocator.deallocate(this, 1); + } + + void* get_deleter(const sp_typeinfo&) { + return &reinterpret_cast(deleter_); + } + + void* get_untyped_deleter() { + return &reinterpret_cast(deleter_); + } + +private: + deleter_type deleter_; + A allocator_; +}; + +#if !defined(BOOST_NO_CXX11_ALLOCATOR) +template +class sp_counted_impl_pda, A> + : public sp_counted_base { +public: + typedef sp_size_array_destroyer deleter_type; + +private: + typedef sp_counted_impl_pda type; + typedef typename sp_bind_allocator::type deallocator; + +public: + sp_counted_impl_pda(P, const deleter_type&, const A& allocator) + : deleter_(allocator) { } + + sp_counted_impl_pda(P, const A& allocator) + : deleter_(allocator) { } + + void dispose() { + deleter_(0); + } + + void destroy() { + this->~type(); + deallocator allocator(deleter_.allocator()); + allocator.deallocate(this, 1); + } + + void* get_deleter(const sp_typeinfo&) { + return &reinterpret_cast(deleter_); + } + + void* get_untyped_deleter() { + return &reinterpret_cast(deleter_); + } + +private: + deleter_type deleter_; +}; +#endif + +template +class sp_counted_impl_pda, + sp_array_allocator > + : public sp_counted_base { +public: + typedef sp_array_deleter deleter_type; + typedef sp_array_allocator allocator_type; + +private: + typedef sp_counted_impl_pda type; + typedef sp_array_allocator::type> deallocator; + +public: + sp_counted_impl_pda(P, const deleter_type&, + const allocator_type& allocator) + : deleter_(allocator), + allocator_(allocator.allocator()) { } + + sp_counted_impl_pda(P, const allocator_type& allocator) + : deleter_(allocator), + allocator_(allocator.allocator()) { } + + void dispose() { + deleter_(0); + } + + void destroy() { + this->~type(); + deallocator allocator(allocator_, deleter_.size()); + allocator.deallocate(this, 1); + } + + void* get_deleter(const sp_typeinfo&) { + return &reinterpret_cast(deleter_); + } + + void* get_untyped_deleter() { + return &reinterpret_cast(deleter_); + } + +private: + deleter_type deleter_; + A allocator_; +}; + +#if !defined(BOOST_NO_CXX11_ALLOCATOR) +template +class sp_counted_impl_pda, + sp_array_allocator > + : public sp_counted_base { +public: + typedef sp_array_destroyer deleter_type; + typedef sp_array_allocator allocator_type; + +private: + typedef sp_counted_impl_pda type; + typedef sp_array_allocator::type> deallocator; + +public: + sp_counted_impl_pda(P, const deleter_type&, + const allocator_type& allocator) + : deleter_(allocator) { } + + sp_counted_impl_pda(P, const allocator_type& allocator) + : deleter_(allocator) { } + + void dispose() { + deleter_(0); + } + + void destroy() { + this->~type(); + deallocator allocator(deleter_.allocator(), deleter_.size()); + allocator.deallocate(this, 1); + } + + void* get_deleter(const sp_typeinfo&) { + return &reinterpret_cast(deleter_); + } + + void* get_untyped_deleter() { + return &reinterpret_cast(deleter_); + } + +private: + deleter_type deleter_; +}; +#endif + +} /* detail */ + +template +inline typename detail::sp_if_size_array::type +allocate_shared(const A& allocator) +{ + typedef typename detail::sp_array_element::type type; + typedef typename detail::sp_array_scalar::type scalar; + typedef typename detail::sp_select_size_deleter::value>::type deleter; + shared_ptr result(static_cast(0), + detail::sp_inplace_tag(), allocator); + deleter* state = detail::sp_get_deleter(result); + void* start = state->construct(); + return shared_ptr(result, static_cast(start)); +} + +template +inline typename detail::sp_if_size_array::type +allocate_shared(const A& allocator, + const typename detail::sp_array_element::type& value) +{ + typedef typename detail::sp_array_element::type type; + typedef typename detail::sp_array_scalar::type scalar; + typedef typename detail::sp_select_size_deleter::value>::type deleter; + shared_ptr result(static_cast(0), + detail::sp_inplace_tag(), allocator); + deleter* state = detail::sp_get_deleter(result); + void* start = state->construct(reinterpret_cast(&value), detail::sp_array_count::value); + return shared_ptr(result, static_cast(start)); +} + +template +inline typename detail::sp_if_size_array::type +allocate_shared_noinit(const A& allocator) +{ + typedef typename detail::sp_array_element::type type; + typedef typename detail::sp_array_scalar::type scalar; + typedef detail::sp_size_array_deleter::value> deleter; + shared_ptr result(static_cast(0), + detail::sp_inplace_tag(), allocator); + deleter* state = detail::sp_get_deleter(result); + void* start = state->construct_default(); + return shared_ptr(result, static_cast(start)); +} + +template +inline typename detail::sp_if_array::type +allocate_shared(const A& allocator, std::size_t count) +{ + typedef typename detail::sp_array_element::type type; + typedef typename detail::sp_array_scalar::type scalar; + typedef typename detail::sp_select_deleter::type deleter; + std::size_t size = count * detail::sp_array_count::value; + void* start; + shared_ptr result(static_cast(0), + detail::sp_inplace_tag(), + detail::sp_array_allocator(allocator, size, &start)); + deleter* state = detail::sp_get_deleter(result); + state->construct(static_cast(start)); + return shared_ptr(result, static_cast(start)); +} + +template +inline typename detail::sp_if_array::type +allocate_shared(const A& allocator, std::size_t count, + const typename detail::sp_array_element::type& value) +{ + typedef typename detail::sp_array_element::type type; + typedef typename detail::sp_array_scalar::type scalar; + typedef typename detail::sp_select_deleter::type deleter; + std::size_t size = count * detail::sp_array_count::value; + void* start; + shared_ptr result(static_cast(0), + detail::sp_inplace_tag(), + detail::sp_array_allocator(allocator, size, &start)); + deleter* state = detail::sp_get_deleter(result); + state->construct(static_cast(start), + reinterpret_cast(&value), + detail::sp_array_count::value); + return shared_ptr(result, static_cast(start)); +} + +template +inline typename detail::sp_if_array::type +allocate_shared_noinit(const A& allocator, std::size_t count) +{ + typedef typename detail::sp_array_element::type type; + typedef typename detail::sp_array_scalar::type scalar; + typedef detail::sp_array_deleter deleter; + std::size_t size = count * detail::sp_array_count::value; + void* start; + shared_ptr result(static_cast(0), + detail::sp_inplace_tag(), + detail::sp_array_allocator(allocator, size, &start)); + deleter* state = detail::sp_get_deleter(result); + state->construct_default(static_cast(start)); + return shared_ptr(result, static_cast(start)); +} + +} /* boost */ + #endif diff --git a/include/boost/smart_ptr/detail/array_allocator.hpp b/include/boost/smart_ptr/detail/array_allocator.hpp deleted file mode 100644 index 7147996..0000000 --- a/include/boost/smart_ptr/detail/array_allocator.hpp +++ /dev/null @@ -1,318 +0,0 @@ -/* - * 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) - */ -#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_ALLOCATOR_HPP -#define BOOST_SMART_PTR_DETAIL_ARRAY_ALLOCATOR_HPP - -#include -#include -#include -#include - -namespace boost { - namespace detail { - struct ms_init_tag { }; - struct ms_noinit_tag { }; - - template - struct ms_allocator_state; - - template - struct ms_allocator_state { - typedef typename array_base::type type; - - ms_allocator_state(std::size_t size_, - type** result_) - : size(size_ * array_total::size), - result(result_) { - } - - std::size_t size; - - union { - type** result; - type* object; - }; - }; - - template - struct ms_allocator_state { - typedef typename array_base::type type; - - ms_allocator_state(type** result_) - : result(result_) { - } - - enum { - size = array_total::size - }; - - union { - type** result; - type* object; - }; - }; - - template - class as_allocator - : public A { - template - friend class as_allocator; - -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - typedef std::allocator_traits AT; - typedef typename AT::template rebind_alloc CA; - typedef typename AT::template rebind_traits CT; -#else - typedef typename A::template rebind::other CA; -#endif - - public: - typedef A allocator_type; - -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - typedef typename AT::value_type value_type; - typedef typename AT::pointer pointer; - typedef typename AT::const_pointer const_pointer; - typedef typename AT::void_pointer void_pointer; - typedef typename AT::const_void_pointer const_void_pointer; - typedef typename AT::size_type size_type; - typedef typename AT::difference_type difference_type; -#else - typedef typename A::value_type value_type; - typedef typename A::pointer pointer; - typedef typename A::const_pointer const_pointer; - typedef typename A::size_type size_type; - typedef typename A::difference_type difference_type; - typedef typename A::reference reference; - typedef typename A::const_reference const_reference; - typedef void* void_pointer; - typedef const void* const_void_pointer; -#endif - - template - struct rebind { -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - typedef as_allocator, T, R> other; -#else - typedef as_allocator::other, T, R> other; -#endif - }; - - typedef typename array_base::type type; - - as_allocator(const A& allocator_, type** result) - : A(allocator_), - data(result) { - } - - as_allocator(const A& allocator_, std::size_t size, - type** result) - : A(allocator_), - data(size, result) { - } - - template - as_allocator(const as_allocator& other) - : A(other.allocator()), - data(other.data) { - } - - pointer allocate(size_type count, const_void_pointer = 0) { - enum { - M = boost::alignment_of::value - }; - std::size_t n1 = count * sizeof(value_type); - std::size_t n2 = data.size * sizeof(type); - std::size_t n3 = n2 + M; - CA ca(allocator()); - void* p1 = ca.allocate(n1 + n3); - void* p2 = static_cast(p1) + n1; - (void)boost::alignment::align(M, n2, p2, n3); - *data.result = static_cast(p2); - return static_cast(p1); - } - - void deallocate(pointer memory, size_type count) { - enum { - M = boost::alignment_of::value - }; - std::size_t n1 = count * sizeof(value_type); - std::size_t n2 = data.size * sizeof(type) + M; - char* p1 = reinterpret_cast(memory); - CA ca(allocator()); - ca.deallocate(p1, n1 + n2); - } - - const A& allocator() const { - return static_cast(*this); - } - - A& allocator() { - return static_cast(*this); - } - - void set(type* memory) { - data.object = memory; - } - - void operator()() { - if (data.object) { - R tag; - release(tag); - } - } - - private: - void release(ms_init_tag) { -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - as_destroy(allocator(), data.object, data.size); -#else - ms_destroy(data.object, data.size); -#endif - } - - void release(ms_noinit_tag) { - ms_destroy(data.object, data.size); - } - - ms_allocator_state data; - }; - - template - bool operator==(const as_allocator& a1, - const as_allocator& a2) { - return a1.allocator() == a2.allocator(); - } - - template - bool operator!=(const as_allocator& a1, - const as_allocator& a2) { - return a1.allocator() != a2.allocator(); - } - - template - class ms_allocator; - - template - class ms_allocator { - template - friend class ms_allocator; - - public: - typedef typename array_base::type type; - - typedef Y value_type; - typedef Y* pointer; - typedef const Y* const_pointer; - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - typedef Y& reference; - typedef const Y& const_reference; - - template - struct rebind { - typedef ms_allocator other; - }; - - ms_allocator(type** result) - : data(result) { - } - - ms_allocator(std::size_t size, type** result) - : data(size, result) { - } - - template - ms_allocator(const ms_allocator& other) - : data(other.data) { - } - - pointer allocate(size_type count, const void* = 0) { - enum { - M = boost::alignment_of::value - }; - std::size_t n1 = count * sizeof(Y); - std::size_t n2 = data.size * sizeof(type); - std::size_t n3 = n2 + M; - void* p1 = ::operator new(n1 + n3); - void* p2 = static_cast(p1) + n1; - (void)boost::alignment::align(M, n2, p2, n3); - *data.result = static_cast(p2); - return static_cast(p1); - } - - void deallocate(pointer memory, size_type) { - void* p1 = memory; - ::operator delete(p1); - } - -#if defined(BOOST_NO_CXX11_ALLOCATOR) - pointer address(reference value) const { - return &value; - } - - const_pointer address(const_reference value) const { - return &value; - } - - size_type max_size() const { - enum { - N = static_cast(-1) / sizeof(Y) - }; - return N; - } - - void construct(pointer memory, const_reference value) { - void* p1 = memory; - ::new(p1) Y(value); - } - - void destroy(pointer memory) { - (void)memory; - memory->~Y(); - } -#endif - - void set(type* memory) { - data.object = memory; - } - - void operator()() { - if (data.object) { - ms_destroy(data.object, data.size); - } - } - - private: - ms_allocator_state data; - }; - - template - bool operator==(const ms_allocator&, - const ms_allocator&) { - return true; - } - - template - bool operator!=(const ms_allocator&, - const ms_allocator&) { - return false; - } - - class ms_in_allocator_tag { - public: - void operator()(const void*) { - } - }; - } -} - -#endif diff --git a/include/boost/smart_ptr/detail/array_count_impl.hpp b/include/boost/smart_ptr/detail/array_count_impl.hpp deleted file mode 100644 index b7c9617..0000000 --- a/include/boost/smart_ptr/detail/array_count_impl.hpp +++ /dev/null @@ -1,67 +0,0 @@ -/* - * 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_ARRAY_COUNT_IMPL_HPP -#define BOOST_SMART_PTR_DETAIL_ARRAY_COUNT_IMPL_HPP - -#include -#include - -namespace boost { - namespace detail { - template - class sp_counted_impl_pda - : public sp_counted_base { - typedef ms_in_allocator_tag D; - typedef sp_counted_impl_pda Y; - public: - sp_counted_impl_pda(P, D, const A& allocator_) - : allocator(allocator_) { - } - - virtual void dispose() { - allocator(); - } - - virtual void destroy() { -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - typedef typename std::allocator_traits:: - template rebind_alloc YA; - typedef typename std::allocator_traits:: - template rebind_traits YT; -#else - typedef typename A::template rebind::other YA; -#endif - YA a1(allocator); -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - YT::destroy(a1, this); - YT::deallocate(a1, this, 1); -#else - this->~Y(); - a1.deallocate(this, 1); -#endif - } - - virtual void* get_deleter(const sp_typeinfo&) { - return &reinterpret_cast(allocator); - } - - virtual void* get_untyped_deleter() { - return &reinterpret_cast(allocator); - } - - private: - sp_counted_impl_pda(const sp_counted_impl_pda&); - sp_counted_impl_pda& operator=(const sp_counted_impl_pda&); - - A allocator; - }; - } -} - -#endif diff --git a/include/boost/smart_ptr/detail/array_traits.hpp b/include/boost/smart_ptr/detail/array_traits.hpp deleted file mode 100644 index 819c5ba..0000000 --- a/include/boost/smart_ptr/detail/array_traits.hpp +++ /dev/null @@ -1,60 +0,0 @@ -/* - * 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) - */ -#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_TRAITS_HPP -#define BOOST_SMART_PTR_DETAIL_ARRAY_TRAITS_HPP - -#include - -namespace boost { - namespace detail { - template - struct array_base { - typedef typename boost::remove_cv::type type; - }; - - template - struct array_base { - typedef typename array_base::type type; - }; - - template - struct array_base { - typedef typename array_base::type type; - }; - - template - struct array_total { - enum { - size = 1 - }; - }; - - template - struct array_total { - enum { - size = N * array_total::size - }; - }; - - template - struct array_inner; - - template - struct array_inner { - typedef T type; - }; - - template - struct array_inner { - typedef T type; - }; - } -} - -#endif diff --git a/include/boost/smart_ptr/detail/array_utility.hpp b/include/boost/smart_ptr/detail/array_utility.hpp deleted file mode 100644 index 84029a1..0000000 --- a/include/boost/smart_ptr/detail/array_utility.hpp +++ /dev/null @@ -1,214 +0,0 @@ -/* - * 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) - */ -#ifndef BOOST_SMART_PTR_DETAIL_ARRAY_UTILITY_HPP -#define BOOST_SMART_PTR_DETAIL_ARRAY_UTILITY_HPP - -#include -#include -#include -#if !defined(BOOST_NO_CXX11_ALLOCATOR) -#include -#endif - -namespace boost { - namespace detail { - typedef boost::true_type ms_is_trivial; - typedef boost::false_type ms_no_trivial; - - template - inline void ms_destroy(T*, std::size_t, ms_is_trivial) { - } - - template - inline void ms_destroy(T* memory, std::size_t size, ms_no_trivial) { - for (std::size_t i = size; i > 0;) { - memory[--i].~T(); - } - } - - template - inline void ms_destroy(T* memory, std::size_t size) { - boost::has_trivial_destructor trivial; - ms_destroy(memory, size, trivial); - } - - template - inline void ms_init(T* memory, std::size_t size, ms_is_trivial) { - for (std::size_t i = 0; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T(); - } - } - - template - inline void ms_init(T* memory, std::size_t size, ms_no_trivial) { -#if !defined(BOOST_NO_EXCEPTIONS) - std::size_t i = 0; - try { - for (; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T(); - } - } catch (...) { - ms_destroy(memory, i); - throw; - } -#else - for (std::size_t i = 0; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T(); - } -#endif - } - - template - inline void ms_init(T* memory, std::size_t size) { - boost::has_trivial_default_constructor trivial; - ms_init(memory, size, trivial); - } - - template - inline void ms_init(T* memory, std::size_t size, const T* list) { -#if !defined(BOOST_NO_EXCEPTIONS) - std::size_t i = 0; - try { - for (; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T(list[i % N]); - } - } catch (...) { - ms_destroy(memory, i); - throw; - } -#else - for (std::size_t i = 0; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T(list[i % N]); - } -#endif - } - -#if !defined(BOOST_NO_CXX11_ALLOCATOR) - template - inline void as_destroy(const A& allocator, T* memory, - std::size_t size) { - typedef typename std::allocator_traits:: - template rebind_alloc TA; - typedef typename std::allocator_traits:: - template rebind_traits TT; - TA a2(allocator); - for (std::size_t i = size; i > 0;) { - TT::destroy(a2, &memory[--i]); - } - } - - template - inline void as_init(const A& allocator, T* memory, std::size_t size, - ms_is_trivial) { - typedef typename std::allocator_traits:: - template rebind_alloc TA; - typedef typename std::allocator_traits:: - template rebind_traits TT; - TA a2(allocator); - for (std::size_t i = 0; i < size; i++) { - TT::construct(a2, memory + i); - } - } - - template - inline void as_init(const A& allocator, T* memory, std::size_t size, - ms_no_trivial) { - typedef typename std::allocator_traits:: - template rebind_alloc TA; - typedef typename std::allocator_traits:: - template rebind_traits TT; - TA a2(allocator); -#if !defined(BOOST_NO_EXCEPTIONS) - std::size_t i = 0; - try { - for (; i < size; i++) { - TT::construct(a2, memory + i); - } - } catch (...) { - as_destroy(a2, memory, i); - throw; - } -#else - for (std::size_t i = 0; i < size; i++) { - TT::construct(a2, memory + i); - } -#endif - } - - template - inline void as_init(const A& allocator, T* memory, std::size_t size) { - boost::has_trivial_default_constructor trivial; - as_init(allocator, memory, size, trivial); - } - - template - inline void as_init(const A& allocator, T* memory, std::size_t size, - const T* list) { - typedef typename std::allocator_traits:: - template rebind_alloc TA; - typedef typename std::allocator_traits:: - template rebind_traits TT; - TA a2(allocator); -#if !defined(BOOST_NO_EXCEPTIONS) - std::size_t i = 0; - try { - for (; i < size; i++) { - TT::construct(a2, memory + i, list[i % N]); - } - } catch (...) { - as_destroy(a2, memory, i); - throw; - } -#else - for (std::size_t i = 0; i < size; i++) { - TT::construct(a2, memory + i, list[i % N]); - } -#endif - } -#endif - - template - inline void ms_noinit(T*, std::size_t, ms_is_trivial) { - } - - template - inline void ms_noinit(T* memory, std::size_t size, ms_no_trivial) { -#if !defined(BOOST_NO_EXCEPTIONS) - std::size_t i = 0; - try { - for (; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T; - } - } catch (...) { - ms_destroy(memory, i); - throw; - } -#else - for (std::size_t i = 0; i < size; i++) { - void* p1 = memory + i; - ::new(p1) T; - } -#endif - } - - template - inline void ms_noinit(T* memory, std::size_t size) { - boost::has_trivial_default_constructor trivial; - ms_noinit(memory, size, trivial); - } - } -} - -#endif diff --git a/include/boost/smart_ptr/detail/sp_if_array.hpp b/include/boost/smart_ptr/detail/sp_if_array.hpp deleted file mode 100644 index 9a2c1e0..0000000 --- a/include/boost/smart_ptr/detail/sp_if_array.hpp +++ /dev/null @@ -1,34 +0,0 @@ -/* - * 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) - */ -#ifndef BOOST_SMART_PTR_DETAIL_SP_IF_ARRAY_HPP -#define BOOST_SMART_PTR_DETAIL_SP_IF_ARRAY_HPP - -#include - -namespace boost { - namespace detail { - template - struct sp_if_array; - - template - struct sp_if_array { - typedef boost::shared_ptr type; - }; - - template - struct sp_if_size_array; - - template - struct sp_if_size_array { - typedef boost::shared_ptr type; - }; - } -} - -#endif diff --git a/include/boost/smart_ptr/make_shared_array.hpp b/include/boost/smart_ptr/make_shared_array.hpp index c48f507..2eaf4db 100644 --- a/include/boost/smart_ptr/make_shared_array.hpp +++ b/include/boost/smart_ptr/make_shared_array.hpp @@ -1,158 +1,66 @@ /* - * 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) - */ +Copyright 2012-2017 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ #ifndef BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP #define BOOST_SMART_PTR_MAKE_SHARED_ARRAY_HPP -#include -#include +#include namespace boost { - template - inline typename boost::detail::sp_if_array::type - make_shared(std::size_t size) { - typedef typename boost::detail::array_inner::type T1; - typedef typename boost::detail::array_base::type T2; - typedef boost::detail::ms_allocator A1; - typedef boost::detail::ms_in_allocator_tag D1; - std::size_t n1 = size * boost::detail::array_total::size; - T1* p1 = 0; - T2* p2 = 0; - D1 d1; - A1 a1(size, &p2); - shared_ptr s1(p1, d1, a1); - A1* a2 = static_cast(s1._internal_get_untyped_deleter()); - a2->set(0); - boost::detail::ms_init(p2, n1); - a2->set(p2); - p1 = reinterpret_cast(p2); - return shared_ptr(s1, p1); - } - template - inline typename boost::detail::sp_if_size_array::type - make_shared() { - typedef typename boost::detail::array_inner::type T1; - typedef typename boost::detail::array_base::type T2; - typedef boost::detail::ms_allocator A1; - typedef boost::detail::ms_in_allocator_tag D1; - enum { - N = boost::detail::array_total::size - }; - T1* p1 = 0; - T2* p2 = 0; - D1 d1; - A1 a1(&p2); - shared_ptr s1(p1, d1, a1); - A1* a2 = static_cast(s1._internal_get_untyped_deleter()); - a2->set(0); - boost::detail::ms_init(p2, N); - a2->set(p2); - p1 = reinterpret_cast(p2); - return shared_ptr(s1, p1); - } - - template - inline typename boost::detail::sp_if_array::type - make_shared(std::size_t size, - const typename boost::detail::array_inner::type& value) { - typedef typename boost::detail::array_inner::type T1; - typedef typename boost::detail::array_base::type T2; - typedef const T2 T3; - typedef boost::detail::ms_allocator A1; - typedef boost::detail::ms_in_allocator_tag D1; - enum { - M = boost::detail::array_total::size - }; - std::size_t n1 = M * size; - T1* p1 = 0; - T2* p2 = 0; - T3* p3 = reinterpret_cast(&value); - D1 d1; - A1 a1(size, &p2); - shared_ptr s1(p1, d1, a1); - A1* a2 = static_cast(s1._internal_get_untyped_deleter()); - a2->set(0); - boost::detail::ms_init(p2, n1, p3); - a2->set(p2); - p1 = reinterpret_cast(p2); - return shared_ptr(s1, p1); - } - - template - inline typename boost::detail::sp_if_size_array::type - make_shared(const typename boost::detail::array_inner::type& value) { - typedef typename boost::detail::array_inner::type T1; - typedef typename boost::detail::array_base::type T2; - typedef const T2 T3; - typedef boost::detail::ms_allocator A1; - typedef boost::detail::ms_in_allocator_tag D1; - enum { - M = boost::detail::array_total::size, - N = boost::detail::array_total::size - }; - T1* p1 = 0; - T2* p2 = 0; - T3* p3 = reinterpret_cast(&value); - D1 d1; - A1 a1(&p2); - shared_ptr s1(p1, d1, a1); - A1* a2 = static_cast(s1._internal_get_untyped_deleter()); - a2->set(0); - boost::detail::ms_init(p2, N, p3); - a2->set(p2); - p1 = reinterpret_cast(p2); - return shared_ptr(s1, p1); - } - - template - inline typename boost::detail::sp_if_array::type - make_shared_noinit(std::size_t size) { - typedef typename boost::detail::array_inner::type T1; - typedef typename boost::detail::array_base::type T2; - typedef boost::detail::ms_allocator A1; - typedef boost::detail::ms_in_allocator_tag D1; - std::size_t n1 = size * boost::detail::array_total::size; - T1* p1 = 0; - T2* p2 = 0; - D1 d1; - A1 a1(size, &p2); - shared_ptr s1(p1, d1, a1); - A1* a2 = static_cast(s1._internal_get_untyped_deleter()); - a2->set(0); - boost::detail::ms_noinit(p2, n1); - a2->set(p2); - p1 = reinterpret_cast(p2); - return shared_ptr(s1, p1); - } - - template - inline typename boost::detail::sp_if_size_array::type - make_shared_noinit() { - typedef typename boost::detail::array_inner::type T1; - typedef typename boost::detail::array_base::type T2; - typedef boost::detail::ms_allocator A1; - typedef boost::detail::ms_in_allocator_tag D1; - enum { - N = boost::detail::array_total::size - }; - T1* p1 = 0; - T2* p2 = 0; - D1 d1; - A1 a1(&p2); - shared_ptr s1(p1, d1, a1); - A1* a2 = static_cast(s1._internal_get_untyped_deleter()); - a2->set(0); - boost::detail::ms_noinit(p2, N); - a2->set(p2); - p1 = reinterpret_cast(p2); - return shared_ptr(s1, p1); - } +template +inline typename detail::sp_if_size_array::type +make_shared() +{ + return boost::allocate_shared(std::allocator::type>()); } +template +inline typename detail::sp_if_size_array::type +make_shared(const typename detail::sp_array_element::type& value) +{ + return boost::allocate_shared(std::allocator::type>(), value); +} + +template +inline typename detail::sp_if_array::type +make_shared(std::size_t size) +{ + return boost::allocate_shared(std::allocator::type>(), size); +} + +template +inline typename detail::sp_if_array::type +make_shared(std::size_t size, + const typename detail::sp_array_element::type& value) +{ + return boost::allocate_shared(std::allocator::type>(), size, value); +} + +template +inline typename detail::sp_if_size_array::type +make_shared_noinit() +{ + return allocate_shared_noinit(std::allocator::type>()); +} + +template +inline typename detail::sp_if_array::type +make_shared_noinit(std::size_t size) +{ + return allocate_shared_noinit(std::allocator::type>(), size); +} + +} /* boost */ + #endif From fb59cd574e2717b89dc8c7d62c8ea25fbbf7c1fc Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Tue, 28 Feb 2017 07:21:49 -0500 Subject: [PATCH 2/8] Copy rebind allocator before impl destruct --- include/boost/smart_ptr/allocate_shared_array.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/boost/smart_ptr/allocate_shared_array.hpp b/include/boost/smart_ptr/allocate_shared_array.hpp index 75adf27..407c103 100644 --- a/include/boost/smart_ptr/allocate_shared_array.hpp +++ b/include/boost/smart_ptr/allocate_shared_array.hpp @@ -748,8 +748,8 @@ public: } void destroy() { - this->~type(); deallocator allocator(allocator_); + this->~type(); allocator.deallocate(this, 1); } @@ -789,8 +789,8 @@ public: } void destroy() { - this->~type(); deallocator allocator(deleter_.allocator()); + this->~type(); allocator.deallocate(this, 1); } @@ -835,8 +835,8 @@ public: } void destroy() { - this->~type(); deallocator allocator(allocator_, deleter_.size()); + this->~type(); allocator.deallocate(this, 1); } @@ -880,8 +880,8 @@ public: } void destroy() { - this->~type(); deallocator allocator(deleter_.allocator(), deleter_.size()); + this->~type(); allocator.deallocate(this, 1); } From 52fbf708796af030ad943d9542ffa443ae1bdc9c Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Tue, 28 Feb 2017 19:01:27 -0500 Subject: [PATCH 3/8] Special case aligning up sizes and change integral constant style --- .../boost/smart_ptr/allocate_shared_array.hpp | 40 ++++++++++++++----- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/include/boost/smart_ptr/allocate_shared_array.hpp b/include/boost/smart_ptr/allocate_shared_array.hpp index 407c103..9d31312 100644 --- a/include/boost/smart_ptr/allocate_shared_array.hpp +++ b/include/boost/smart_ptr/allocate_shared_array.hpp @@ -93,13 +93,16 @@ struct sp_array_scalar { template struct sp_array_count { - BOOST_STATIC_CONSTEXPR std::size_t value = 1; + enum { + value = 1 + }; }; template struct sp_array_count { - BOOST_STATIC_CONSTEXPR std::size_t value = N * - sp_array_count::value; + enum { + value = N * sp_array_count::value + }; }; template @@ -122,7 +125,9 @@ struct sp_array_storage { template struct sp_max_size { - BOOST_STATIC_CONSTEXPR std::size_t value = N < M ? M : N; + enum { + value = N < M ? M : N + }; }; #if !defined(BOOST_NO_CXX11_ALLOCATOR) @@ -138,12 +143,12 @@ struct sp_bind_allocator { }; #endif -template +template struct sp_enable { }; -template<> -struct sp_enable { - typedef void type; +template +struct sp_enable { + typedef T type; }; template @@ -344,6 +349,14 @@ sp_array_default(T* storage, std::size_t size) } #endif +template +struct sp_less_align { + enum { + value = (boost::alignment_of::value < + boost::alignment_of::value) + }; +}; + template BOOST_CONSTEXPR inline std::size_t sp_objects(std::size_t size) BOOST_NOEXCEPT @@ -352,12 +365,21 @@ sp_objects(std::size_t size) BOOST_NOEXCEPT } template -BOOST_CONSTEXPR inline std::size_t +BOOST_CONSTEXPR inline +typename sp_enable::value, std::size_t>::type sp_align(std::size_t size) BOOST_NOEXCEPT { return (sizeof(T) * size + sizeof(U) - 1) & ~(sizeof(U) - 1); } +template +BOOST_CONSTEXPR inline +typename sp_enable::value, std::size_t>::type +sp_align(std::size_t size) BOOST_NOEXCEPT +{ + return sizeof(T) * size; +} + template class sp_size_array_deleter { public: From f8524c42a8477986045a9b05833926ac510ad53d Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 1 Mar 2017 12:02:30 +0200 Subject: [PATCH 4/8] Add test for a MSVC parsing problem in make_shared --- test/Jamfile.v2 | 2 ++ test/make_shared_msvc_test.cpp | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 test/make_shared_msvc_test.cpp diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 5248d36..1814bd8 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -205,5 +205,7 @@ import testing ; [ compile-fail pointer_cast_dy_fail3.cpp ] [ run sp_nothrow_test.cpp ] + + [ compile make_shared_msvc_test.cpp ] ; } diff --git a/test/make_shared_msvc_test.cpp b/test/make_shared_msvc_test.cpp new file mode 100644 index 0000000..84de4a5 --- /dev/null +++ b/test/make_shared_msvc_test.cpp @@ -0,0 +1,19 @@ +// +// make_shared_msvc_test.cpp +// +// Copyright 2017 Peter Dimov +// +// Distributed under the Boost Software License, Version 1.0. +// See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt +// + +template struct value +{ +}; + +#include + +int main() +{ +} From 1f9c63c34f0fb18cac1709654578e10ce4dcc889 Mon Sep 17 00:00:00 2001 From: Peter Dimov Date: Wed, 1 Mar 2017 12:08:17 +0200 Subject: [PATCH 5/8] Fix MSVC parsing problem in allocate_shared_array --- include/boost/smart_ptr/allocate_shared_array.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/boost/smart_ptr/allocate_shared_array.hpp b/include/boost/smart_ptr/allocate_shared_array.hpp index 9d31312..e7d0964 100644 --- a/include/boost/smart_ptr/allocate_shared_array.hpp +++ b/include/boost/smart_ptr/allocate_shared_array.hpp @@ -352,7 +352,7 @@ sp_array_default(T* storage, std::size_t size) template struct sp_less_align { enum { - value = (boost::alignment_of::value < + value = ((boost::alignment_of::value) < boost::alignment_of::value) }; }; From b42acf77b3eaac32d7dca609ac9e40afb0f7c239 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Tue, 28 Feb 2017 07:29:21 -0500 Subject: [PATCH 6/8] Only use allocator construct/destroy for value_type, not shared_count --- .../boost/smart_ptr/detail/shared_count.hpp | 62 ++----------------- .../smart_ptr/detail/sp_counted_impl.hpp | 8 --- 2 files changed, 4 insertions(+), 66 deletions(-) diff --git a/include/boost/smart_ptr/detail/shared_count.hpp b/include/boost/smart_ptr/detail/shared_count.hpp index 7996aa4..9813842 100644 --- a/include/boost/smart_ptr/detail/shared_count.hpp +++ b/include/boost/smart_ptr/detail/shared_count.hpp @@ -249,18 +249,8 @@ public: try { -#if !defined( BOOST_NO_CXX11_ALLOCATOR ) - - impl_type * pi = std::allocator_traits::allocate( a2, 1 ); - pi_ = pi; - std::allocator_traits::construct( a2, pi, p, d, a ); - -#else - - pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) ); + pi_ = a2.allocate( 1 ); ::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a ); - -#endif } catch(...) { @@ -276,28 +266,11 @@ public: #else -#if !defined( BOOST_NO_CXX11_ALLOCATOR ) - - impl_type * pi = std::allocator_traits::allocate( a2, 1 ); - pi_ = pi; - -#else - - pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) ); - -#endif + pi_ = a2.allocate( 1 ); if( pi_ != 0 ) { -#if !defined( BOOST_NO_CXX11_ALLOCATOR ) - - std::allocator_traits::construct( a2, pi, p, d, a ); - -#else - ::new( static_cast< void* >( pi_ ) ) impl_type( p, d, a ); - -#endif } else { @@ -333,18 +306,8 @@ public: try { -#if !defined( BOOST_NO_CXX11_ALLOCATOR ) - - impl_type * pi = std::allocator_traits::allocate( a2, 1 ); - pi_ = pi; - std::allocator_traits::construct( a2, pi, p, a ); - -#else - - pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) ); + pi_ = a2.allocate( 1 ); ::new( static_cast< void* >( pi_ ) ) impl_type( p, a ); - -#endif } catch(...) { @@ -360,28 +323,11 @@ public: #else -#if !defined( BOOST_NO_CXX11_ALLOCATOR ) - - impl_type * pi = std::allocator_traits::allocate( a2, 1 ); - pi_ = pi; - -#else - - pi_ = a2.allocate( 1, static_cast< impl_type* >( 0 ) ); - -#endif + pi_ = a2.allocate( 1 ); if( pi_ != 0 ) { -#if !defined( BOOST_NO_CXX11_ALLOCATOR ) - - std::allocator_traits::construct( a2, pi, p, a ); - -#else - ::new( static_cast< void* >( pi_ ) ) impl_type( p, a ); - -#endif } else { diff --git a/include/boost/smart_ptr/detail/sp_counted_impl.hpp b/include/boost/smart_ptr/detail/sp_counted_impl.hpp index 1222f3c..b29769e 100644 --- a/include/boost/smart_ptr/detail/sp_counted_impl.hpp +++ b/include/boost/smart_ptr/detail/sp_counted_impl.hpp @@ -236,16 +236,8 @@ public: A2 a2( a_ ); -#if !defined( BOOST_NO_CXX11_ALLOCATOR ) - - std::allocator_traits::destroy( a2, this ); - -#else - this->~this_type(); -#endif - a2.deallocate( this, 1 ); } From 7570340d709d9981c6737659e5e98f7979d3152c Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Tue, 28 Feb 2017 14:00:23 -0500 Subject: [PATCH 7/8] Add test for allocator construct usage --- test/Jamfile.v2 | 1 + test/shared_ptr_alloc_construct11_test.cpp | 128 +++++++++++++++++++++ 2 files changed, 129 insertions(+) create mode 100644 test/shared_ptr_alloc_construct11_test.cpp diff --git a/test/Jamfile.v2 b/test/Jamfile.v2 index 1814bd8..528fe06 100644 --- a/test/Jamfile.v2 +++ b/test/Jamfile.v2 @@ -84,6 +84,7 @@ import testing ; [ run sa_nullptr_test.cpp ] [ run shared_ptr_alloc3_test.cpp ] [ run shared_ptr_alloc11_test.cpp ] + [ run shared_ptr_alloc_construct11_test.cpp ] [ run allocate_shared_alloc11_test.cpp ] [ run allocate_shared_construct11_test.cpp ] [ run sp_interlocked_test.cpp ] diff --git a/test/shared_ptr_alloc_construct11_test.cpp b/test/shared_ptr_alloc_construct11_test.cpp new file mode 100644 index 0000000..436f828 --- /dev/null +++ b/test/shared_ptr_alloc_construct11_test.cpp @@ -0,0 +1,128 @@ +/* +Copyright 2017 Glen Joseph Fernandes +(glenjofe@gmail.com) + +Distributed under the Boost Software License, Version 1.0. +(http://www.boost.org/LICENSE_1_0.txt) +*/ +#include +#include + +#if !defined(BOOST_NO_CXX11_ALLOCATOR) +struct counters { + unsigned allocate; + unsigned construct; +}; + +template +class creator { +public: + typedef T value_type; + + creator(counters* state) + : state_(state) { } + + template + creator(const creator& other) + : state_(other.state()) { } + + T* allocate(std::size_t size) { + void* ptr = ::operator new(sizeof(T) * size); + ++state_->allocate; + return static_cast(ptr); + } + + void deallocate(T* ptr, std::size_t) { + ::operator delete(ptr); + --state_->allocate; + } + + template + void construct(T* ptr, Args&&... args) { + ::new(static_cast(ptr)) T(std::forward(args)...); + ++state_->construct; + } + + void destroy(T* ptr) { + ptr->~T(); + --state_->construct; + } + + counters* state() const { + return state_; + } + +private: + counters* state_; +}; + +template +inline bool +operator==(const creator& lhs, const creator& rhs) +{ + return lhs.state() == rhs.state(); +} + +template +inline bool +operator!=(const creator& lhs, const creator& rhs) +{ + return !(lhs == rhs); +} + +struct deleter { + template + void operator()(U ptr) const { + delete ptr; + } +}; + +int main() +{ + { + counters state = { }; + boost::shared_ptr pointer(new int(), deleter(), + creator(&state)); + BOOST_TEST(state.allocate == 1); + BOOST_TEST(state.construct == 0); + pointer.reset(); + BOOST_TEST(state.allocate == 0); + } + { + counters state = { }; + boost::shared_ptr pointer = + boost::allocate_shared(creator(&state)); + BOOST_TEST(state.allocate == 1); + BOOST_TEST(state.construct == 1); + pointer.reset(); + BOOST_TEST(state.allocate == 0); + BOOST_TEST(state.construct == 0); + } + { + counters state = { }; + boost::shared_ptr pointer = + boost::allocate_shared(creator(&state), 5); + BOOST_TEST(state.allocate == 1); + BOOST_TEST(state.construct == 5); + pointer.reset(); + BOOST_TEST(state.allocate == 0); + BOOST_TEST(state.construct == 0); + } + { + counters state = { }; + boost::shared_ptr pointer = + boost::allocate_shared(creator(&state)); + BOOST_TEST(state.allocate == 1); + BOOST_TEST(state.construct == 5); + pointer.reset(); + BOOST_TEST(state.allocate == 0); + BOOST_TEST(state.construct == 0); + } + return boost::report_errors(); +} +#else +int main() +{ + return 0; +} +#endif From d1bb87d34e3275017074510445d95ec2300cc839 Mon Sep 17 00:00:00 2001 From: Glen Fernandes Date: Wed, 1 Mar 2017 08:57:58 -0500 Subject: [PATCH 8/8] Remove the now unnecessary allocate hint parameter --- include/boost/smart_ptr/allocate_shared_array.hpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/boost/smart_ptr/allocate_shared_array.hpp b/include/boost/smart_ptr/allocate_shared_array.hpp index e7d0964..90c5614 100644 --- a/include/boost/smart_ptr/allocate_shared_array.hpp +++ b/include/boost/smart_ptr/allocate_shared_array.hpp @@ -352,8 +352,8 @@ sp_array_default(T* storage, std::size_t size) template struct sp_less_align { enum { - value = ((boost::alignment_of::value) < - boost::alignment_of::value) + value = (boost::alignment_of::value) < + (boost::alignment_of::value) }; }; @@ -664,7 +664,7 @@ public: size_(other.size_), result_(other.result_) { } - value_type* allocate(std::size_t count, const void* = 0) { + value_type* allocate(std::size_t count) { type_allocator allocator(allocator_); std::size_t head = sp_align(count); std::size_t tail = sp_align(size_);