diff options
Diffstat (limited to 'boost/smart_ptr/allocate_shared_array.hpp')
-rw-r--r-- | boost/smart_ptr/allocate_shared_array.hpp | 1163 |
1 files changed, 1004 insertions, 159 deletions
diff --git a/boost/smart_ptr/allocate_shared_array.hpp b/boost/smart_ptr/allocate_shared_array.hpp index 1ae5cc7832..b43b43d575 100644 --- a/boost/smart_ptr/allocate_shared_array.hpp +++ b/boost/smart_ptr/allocate_shared_array.hpp @@ -1,181 +1,1026 @@ /* - * 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 <boost/smart_ptr/detail/array_count_impl.hpp> -#include <boost/smart_ptr/detail/sp_if_array.hpp> +#include <boost/smart_ptr/shared_ptr.hpp> +#include <boost/type_traits/has_trivial_constructor.hpp> +#include <boost/type_traits/has_trivial_destructor.hpp> +#include <boost/type_traits/alignment_of.hpp> +#include <boost/type_traits/type_with_alignment.hpp> namespace boost { - template<class T, class A> - inline typename boost::detail::sp_if_array<T>::type - allocate_shared(const A& allocator, std::size_t size) { - typedef typename boost::detail::array_inner<T>::type T1; - typedef typename boost::detail::array_base<T1>::type T2; - typedef boost::detail::ms_init_tag R1; - typedef boost::detail::as_allocator<A, T, R1> A1; - typedef boost::detail::ms_in_allocator_tag D1; - std::size_t n1 = size * boost::detail::array_total<T1>::size; - T1* p1 = 0; - T2* p2 = 0; - D1 d1; - A1 a1(allocator, size, &p2); - shared_ptr<T> s1(p1, d1, a1); - A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter()); - a2->set(0); +namespace detail { + +template<class> +struct sp_if_array { }; + +template<class T> +struct sp_if_array<T[]> { + typedef boost::shared_ptr<T[]> type; +}; + +template<class> +struct sp_if_size_array { }; + +template<class T, std::size_t N> +struct sp_if_size_array<T[N]> { + typedef boost::shared_ptr<T[N]> type; +}; + +template<class> +struct sp_array_element { }; + +template<class T> +struct sp_array_element<T[]> { + typedef T type; +}; + +template<class T, std::size_t N> +struct sp_array_element<T[N]> { + typedef T type; +}; + +template<class T> +struct sp_array_scalar { + typedef T type; +}; + +template<class T, std::size_t N> +struct sp_array_scalar<T[N]> { + typedef typename sp_array_scalar<T>::type type; +}; + +template<class T, std::size_t N> +struct sp_array_scalar<const T[N]> { + typedef typename sp_array_scalar<T>::type type; +}; + +template<class T, std::size_t N> +struct sp_array_scalar<volatile T[N]> { + typedef typename sp_array_scalar<T>::type type; +}; + +template<class T, std::size_t N> +struct sp_array_scalar<const volatile T[N]> { + typedef typename sp_array_scalar<T>::type type; +}; + +template<class T> +struct sp_array_scalar<T[]> { + typedef typename sp_array_scalar<T>::type type; +}; + +template<class T> +struct sp_array_scalar<const T[]> { + typedef typename sp_array_scalar<T>::type type; +}; + +template<class T> +struct sp_array_scalar<volatile T[]> { + typedef typename sp_array_scalar<T>::type type; +}; + +template<class T> +struct sp_array_scalar<const volatile T[]> { + typedef typename sp_array_scalar<T>::type type; +}; + +template<class T> +struct sp_array_count { + enum { + value = 1 + }; +}; + +template<class T, std::size_t N> +struct sp_array_count<T[N]> { + enum { + value = N * sp_array_count<T>::value + }; +}; + +template<class T> +struct sp_array_count<T[]> { }; + +template<class D, class T> +inline D* +sp_get_deleter(const + boost::shared_ptr<T>& value) BOOST_NOEXCEPT_OR_NOTHROW +{ + return static_cast<D*>(value._internal_get_untyped_deleter()); +} + +template<std::size_t N, std::size_t A> +struct sp_array_storage { + union type { + char value[N]; + typename boost::type_with_alignment<A>::type other; + }; +}; + +template<std::size_t N, std::size_t M> +struct sp_max_size { + enum { + value = N < M ? M : N + }; +}; + #if !defined(BOOST_NO_CXX11_ALLOCATOR) - boost::detail::as_init(allocator, p2, n1); +template<class A, class T> +struct sp_bind_allocator { + typedef typename std::allocator_traits<A>::template + rebind_alloc<T> type; +}; #else - boost::detail::ms_init(p2, n1); +template<class A, class T> +struct sp_bind_allocator { + typedef typename A::template rebind<T>::other type; +}; #endif - a2->set(p2); - p1 = reinterpret_cast<T1*>(p2); - return shared_ptr<T>(s1, p1); - } - - template<class T, class A> - inline typename boost::detail::sp_if_size_array<T>::type - allocate_shared(const A& allocator) { - typedef typename boost::detail::array_inner<T>::type T1; - typedef typename boost::detail::array_base<T1>::type T2; - typedef boost::detail::ms_init_tag R1; - typedef boost::detail::as_allocator<A, T, R1> A1; - typedef boost::detail::ms_in_allocator_tag D1; - enum { - N = boost::detail::array_total<T>::size - }; - T1* p1 = 0; - T2* p2 = 0; - D1 d1; - A1 a1(allocator, &p2); - shared_ptr<T> s1(p1, d1, a1); - A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter()); - a2->set(0); + +template<bool, class = void> +struct sp_enable { }; + +template<class T> +struct sp_enable<true, T> { + typedef T type; +}; + +template<class T> +inline +typename sp_enable<boost::has_trivial_destructor<T>::value>::type +sp_array_destroy(T*, std::size_t) BOOST_NOEXCEPT { } + +template<class T> +inline +typename sp_enable<!boost::has_trivial_destructor<T>::value>::type +sp_array_destroy(T* storage, std::size_t size) +{ + while (size > 0) { + storage[--size].~T(); + } +} + #if !defined(BOOST_NO_CXX11_ALLOCATOR) - boost::detail::as_init(allocator, p2, N); +template<class A, class T> +inline void +sp_array_destroy(A& allocator, T* storage, std::size_t size) +{ + while (size > 0) { + std::allocator_traits<A>::destroy(allocator, &storage[--size]); + } +} +#endif + +#if !defined(BOOST_NO_EXCEPTIONS) +template<class T> +inline +typename sp_enable<boost::has_trivial_constructor<T>::value || + boost::has_trivial_destructor<T>::value>::type +sp_array_construct(T* storage, std::size_t size) +{ + for (std::size_t i = 0; i < size; ++i) { + ::new(static_cast<void*>(storage + i)) T(); + } +} + +template<class T> +inline +typename sp_enable<!boost::has_trivial_constructor<T>::value && + !boost::has_trivial_destructor<T>::value>::type +sp_array_construct(T* storage, std::size_t size) +{ + std::size_t i = 0; + try { + for (; i < size; ++i) { + ::new(static_cast<void*>(storage + i)) T(); + } + } catch (...) { + while (i > 0) { + storage[--i].~T(); + } + throw; + } +} + +template<class T> +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<void*>(storage + i)) T(list[i % count]); + } + } catch (...) { + while (i > 0) { + storage[--i].~T(); + } + throw; + } +} #else - boost::detail::ms_init(p2, N); +template<class T> +inline void +sp_array_construct(T* storage, std::size_t size) +{ + for (std::size_t i = 0; i < size; ++i) { + ::new(static_cast<void*>(storage + i)) T(); + } +} + +template<class T> +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<void*>(storage + i)) T(list[i % count]); + } +} #endif - a2->set(p2); - p1 = reinterpret_cast<T1*>(p2); - return shared_ptr<T>(s1, p1); - } - - template<class T, class A> - inline typename boost::detail::sp_if_array<T>::type - allocate_shared(const A& allocator, std::size_t size, - const typename boost::detail::array_inner<T>::type& value) { - typedef typename boost::detail::array_inner<T>::type T1; - typedef typename boost::detail::array_base<T1>::type T2; - typedef const T2 T3; - typedef boost::detail::ms_init_tag R1; - typedef boost::detail::as_allocator<A, T, R1> A1; - typedef boost::detail::ms_in_allocator_tag D1; - enum { - M = boost::detail::array_total<T1>::size - }; - std::size_t n1 = M * size; - T1* p1 = 0; - T2* p2 = 0; - T3* p3 = reinterpret_cast<T3*>(&value); - D1 d1; - A1 a1(allocator, size, &p2); - shared_ptr<T> s1(p1, d1, a1); - A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter()); - a2->set(0); + #if !defined(BOOST_NO_CXX11_ALLOCATOR) - boost::detail::as_init<T2, A, M>(allocator, p2, n1, p3); +#if !defined(BOOST_NO_EXCEPTIONS) +template<class A, class T> +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<A>::construct(allocator, storage + i); + } + } catch (...) { + sp_array_destroy(allocator, storage, i); + throw; + } +} + +template<class A, class T> +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<A>::construct(allocator, storage + i, + list[i % count]); + } + } catch (...) { + sp_array_destroy(allocator, storage, i); + throw; + } +} #else - boost::detail::ms_init<T2, M>(p2, n1, p3); +template<class A, class T> +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<A>::construct(allocator, storage + i); + } +} + +template<class A, class T> +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<A>::construct(allocator, storage + i, + list[i % count]); + } +} +#endif #endif - a2->set(p2); - p1 = reinterpret_cast<T1*>(p2); - return shared_ptr<T>(s1, p1); - } - - template<class T, class A> - inline typename boost::detail::sp_if_size_array<T>::type - allocate_shared(const A& allocator, - const typename boost::detail::array_inner<T>::type& value) { - typedef typename boost::detail::array_inner<T>::type T1; - typedef typename boost::detail::array_base<T1>::type T2; - typedef const T2 T3; - typedef boost::detail::ms_init_tag R1; - typedef boost::detail::as_allocator<A, T, R1> A1; - typedef boost::detail::ms_in_allocator_tag D1; - enum { - N = boost::detail::array_total<T>::size, - M = boost::detail::array_total<T1>::size - }; - T1* p1 = 0; - T2* p2 = 0; - T3* p3 = reinterpret_cast<T3*>(&value); - D1 d1; - A1 a1(allocator, &p2); - shared_ptr<T> s1(p1, d1, a1); - A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter()); - a2->set(0); + +template<class T> +inline +typename sp_enable<boost::has_trivial_constructor<T>::value>::type +sp_array_default(T*, std::size_t) BOOST_NOEXCEPT { } + +#if !defined(BOOST_NO_EXCEPTIONS) +template<class T> +inline +typename sp_enable<!boost::has_trivial_constructor<T>::value && + boost::has_trivial_destructor<T>::value>::type +sp_array_default(T* storage, std::size_t size) +{ + for (std::size_t i = 0; i < size; ++i) { + ::new(static_cast<void*>(storage + i)) T; + } +} + +template<class T> +inline +typename sp_enable<!boost::has_trivial_constructor<T>::value && + !boost::has_trivial_destructor<T>::value>::type +sp_array_default(T* storage, std::size_t size) +{ + std::size_t i = 0; + try { + for (; i < size; ++i) { + ::new(static_cast<void*>(storage + i)) T; + } + } catch (...) { + while (i > 0) { + storage[--i].~T(); + } + throw; + } +} +#else +template<class T> +inline +typename sp_enable<!boost::has_trivial_constructor<T>::value>::type +sp_array_default(T* storage, std::size_t size) +{ + for (std::size_t i = 0; i < size; ++i) { + ::new(static_cast<void*>(storage + i)) T; + } +} +#endif + +template<class T, std::size_t N> +struct sp_less_align { + enum { + value = (boost::alignment_of<T>::value) < N + }; +}; + +template<class T, std::size_t N> +BOOST_CONSTEXPR inline +typename sp_enable<sp_less_align<T, N>::value, std::size_t>::type +sp_align(std::size_t size) BOOST_NOEXCEPT +{ + return (sizeof(T) * size + N - 1) & ~(N - 1); +} + +template<class T, std::size_t N> +BOOST_CONSTEXPR inline +typename sp_enable<!sp_less_align<T, N>::value, std::size_t>::type +sp_align(std::size_t size) BOOST_NOEXCEPT +{ + return sizeof(T) * size; +} + +template<class T> +BOOST_CONSTEXPR inline std::size_t +sp_types(std::size_t size) BOOST_NOEXCEPT +{ + return (size + sizeof(T) - 1) / sizeof(T); +} + +template<class T, std::size_t N> +class sp_size_array_deleter { +public: + template<class U> + static void operator_fn(U) BOOST_NOEXCEPT { } + + sp_size_array_deleter() BOOST_NOEXCEPT + : enabled_(false) { } + + template<class A> + 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<T*>(&storage_), N); + } + } + + template<class U> + void operator()(U) { + if (enabled_) { + sp_array_destroy(reinterpret_cast<T*>(&storage_), N); + enabled_ = false; + } + } + + void* construct() { + sp_array_construct(reinterpret_cast<T*>(&storage_), N); + enabled_ = true; + return &storage_; + } + + void* construct(const T* list, std::size_t count) { + sp_array_construct(reinterpret_cast<T*>(&storage_), N, + list, count); + enabled_ = true; + return &storage_; + } + + void* construct_default() { + sp_array_default(reinterpret_cast<T*>(&storage_), N); + enabled_ = true; + return &storage_; + } + +private: + bool enabled_; + typename sp_array_storage<sizeof(T) * N, + boost::alignment_of<T>::value>::type storage_; +}; + #if !defined(BOOST_NO_CXX11_ALLOCATOR) - boost::detail::as_init<T2, A, M>(allocator, p2, N, p3); +template<class T, std::size_t N, class A> +class sp_size_array_destroyer { +public: + template<class U> + static void operator_fn(U) BOOST_NOEXCEPT { } + + template<class U> + 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<T*>(&storage_), N); + } + } + + template<class U> + void operator()(U) { + if (enabled_) { + sp_array_destroy(allocator_, + reinterpret_cast<T*>(&storage_), N); + enabled_ = false; + } + } + + void* construct() { + sp_array_construct(allocator_, + reinterpret_cast<T*>(&storage_), N); + enabled_ = true; + return &storage_; + } + + void* construct(const T* list, std::size_t count) { + sp_array_construct(allocator_, + reinterpret_cast<T*>(&storage_), N, list, count); + enabled_ = true; + return &storage_; + } + + const A& allocator() const BOOST_NOEXCEPT { + return allocator_; + } + +private: + typename sp_array_storage<sizeof(T) * N, + boost::alignment_of<T>::value>::type storage_; + A allocator_; + bool enabled_; +}; +#endif + +template<class T> +class sp_array_deleter { +public: + template<class U> + static void operator_fn(U) BOOST_NOEXCEPT { } + + sp_array_deleter(std::size_t size) BOOST_NOEXCEPT + : address_(0), + size_(size) { } + + template<class A> + sp_array_deleter(const A& allocator) BOOST_NOEXCEPT + : address_(0), + size_(allocator.size()) { } + + template<class A> + 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<T*>(address_), size_); + } + } + + template<class U> + void operator()(U) { + if (address_) { + sp_array_destroy(static_cast<T*>(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 T, class A> +class sp_array_destroyer { +public: + template<class U> + static void operator_fn(U) BOOST_NOEXCEPT { } + + template<class U> + sp_array_destroyer(const U& allocator, std::size_t size) + BOOST_NOEXCEPT + : allocator_(allocator), + size_(size), + address_(0) { } + + template<class U> + 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<T*>(address_), + size_); + } + } + + template<class U> + void operator()(U) { + if (address_) { + sp_array_destroy(allocator_, static_cast<T*>(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 T, class A> +class sp_array_allocator { + template<class U, class V> + friend class sp_array_allocator; + +public: + typedef typename A::value_type value_type; + +private: + enum { + alignment = sp_max_size<boost::alignment_of<T>::value, + boost::alignment_of<value_type>::value>::value + }; + + typedef typename boost::type_with_alignment<alignment>::type type; + typedef typename sp_bind_allocator<A, type>::type type_allocator; + +public: + template<class U> + struct rebind { + typedef sp_array_allocator<T, + typename sp_bind_allocator<A, U>::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<class U> + sp_array_allocator(const sp_array_allocator<T, U>& other) + BOOST_NOEXCEPT + : allocator_(other.allocator_), + size_(other.size_), + result_(other.result_) { } + + value_type* allocate(std::size_t count) { + type_allocator allocator(allocator_); + std::size_t node = sp_align<value_type, alignment>(count); + std::size_t size = sp_types<type>(node + sizeof(T) * size_); + type* address = allocator.allocate(size); + *result_ = reinterpret_cast<char*>(address) + node; + return reinterpret_cast<value_type*>(address); + } + + void deallocate(value_type* value, std::size_t count) { + type_allocator allocator(allocator_); + std::size_t node = sp_align<value_type, alignment>(count); + std::size_t size = sp_types<type>(node + sizeof(T) * size_); + allocator.deallocate(reinterpret_cast<type*>(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<class T, class U, class V> +inline bool +operator==(const sp_array_allocator<T, U>& first, + const sp_array_allocator<T, V>& second) BOOST_NOEXCEPT +{ + return first.allocator() == second.allocator() && + first.size() == second.size(); +} + +template<class T, class U, class V> +inline bool +operator!=(const sp_array_allocator<T, U>& first, + const sp_array_allocator<T, V>& second) BOOST_NOEXCEPT +{ + return !(first == second); +} + +#if !defined(BOOST_NO_CXX11_ALLOCATOR) +template<class A, class T, std::size_t N> +struct sp_select_size_deleter { + typedef sp_size_array_destroyer<T, N, + typename sp_bind_allocator<A, T>::type> type; +}; + +template<class U, class T, std::size_t N> +struct sp_select_size_deleter<std::allocator<U>, T, N> { + typedef sp_size_array_deleter<T, N> type; +}; + +template<class A, class T> +struct sp_select_deleter { + typedef sp_array_destroyer<T, + typename sp_bind_allocator<A, T>::type> type; +}; + +template<class U, class T> +struct sp_select_deleter<std::allocator<U>, T> { + typedef sp_array_deleter<T> type; +}; #else - boost::detail::ms_init<T2, M>(p2, N, p3); +template<class, class T, std::size_t N> +struct sp_select_size_deleter { + typedef sp_size_array_deleter<T, N> type; +}; + +template<class, class T> +struct sp_select_deleter { + typedef sp_array_deleter<T> type; +}; +#endif + +template<class P, class T, std::size_t N, class A> +class sp_counted_impl_pda<P, sp_size_array_deleter<T, N>, A> + : public sp_counted_base { +public: + typedef sp_size_array_deleter<T, N> deleter_type; + +private: + typedef sp_counted_impl_pda<P, deleter_type, A> type; + typedef typename sp_bind_allocator<A, type>::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() { + deallocator allocator(allocator_); + this->~type(); + allocator.deallocate(this, 1); + } + + void* get_deleter(const sp_typeinfo&) { + return &reinterpret_cast<char&>(deleter_); + } + + void* get_untyped_deleter() { + return &reinterpret_cast<char&>(deleter_); + } + +private: + deleter_type deleter_; + A allocator_; +}; + +#if !defined(BOOST_NO_CXX11_ALLOCATOR) +template<class P, class T, std::size_t N, class U, class A> +class sp_counted_impl_pda<P, sp_size_array_destroyer<T, N, U>, A> + : public sp_counted_base { +public: + typedef sp_size_array_destroyer<T, N, U> deleter_type; + +private: + typedef sp_counted_impl_pda<P, deleter_type, A> type; + typedef typename sp_bind_allocator<A, type>::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() { + deallocator allocator(deleter_.allocator()); + this->~type(); + allocator.deallocate(this, 1); + } + + void* get_deleter(const sp_typeinfo&) { + return &reinterpret_cast<char&>(deleter_); + } + + void* get_untyped_deleter() { + return &reinterpret_cast<char&>(deleter_); + } + +private: + deleter_type deleter_; +}; #endif - a2->set(p2); - p1 = reinterpret_cast<T1*>(p2); - return shared_ptr<T>(s1, p1); - } - - template<class T, class A> - inline typename boost::detail::sp_if_array<T>::type - allocate_shared_noinit(const A& allocator, std::size_t size) { - typedef typename boost::detail::array_inner<T>::type T1; - typedef typename boost::detail::array_base<T1>::type T2; - typedef boost::detail::ms_noinit_tag R1; - typedef boost::detail::as_allocator<A, T, R1> A1; - typedef boost::detail::ms_in_allocator_tag D1; - std::size_t n1 = size * boost::detail::array_total<T1>::size; - T1* p1 = 0; - T2* p2 = 0; - D1 d1; - A1 a1(allocator, size, &p2); - shared_ptr<T> s1(p1, d1, a1); - A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter()); - a2->set(0); - boost::detail::ms_noinit(p2, n1); - a2->set(p2); - p1 = reinterpret_cast<T1*>(p2); - return shared_ptr<T>(s1, p1); - } - - template<class T, class A> - inline typename boost::detail::sp_if_size_array<T>::type - allocate_shared_noinit(const A& allocator) { - typedef typename boost::detail::array_inner<T>::type T1; - typedef typename boost::detail::array_base<T1>::type T2; - typedef boost::detail::ms_noinit_tag R1; - typedef boost::detail::as_allocator<A, T, R1> A1; - typedef boost::detail::ms_in_allocator_tag D1; - enum { - N = boost::detail::array_total<T>::size - }; - T1* p1 = 0; - T2* p2 = 0; - D1 d1; - A1 a1(allocator, &p2); - shared_ptr<T> s1(p1, d1, a1); - A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter()); - a2->set(0); - boost::detail::ms_noinit(p2, N); - a2->set(p2); - p1 = reinterpret_cast<T1*>(p2); - return shared_ptr<T>(s1, p1); + +template<class P, class T, class A> +class sp_counted_impl_pda<P, sp_array_deleter<T>, + sp_array_allocator<T, A> > + : public sp_counted_base { +public: + typedef sp_array_deleter<T> deleter_type; + typedef sp_array_allocator<T, A> allocator_type; + +private: + typedef sp_counted_impl_pda<P, deleter_type, allocator_type> type; + typedef sp_array_allocator<T, + typename sp_bind_allocator<A, type>::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() { + deallocator allocator(allocator_, deleter_.size()); + this->~type(); + allocator.deallocate(this, 1); + } + + void* get_deleter(const sp_typeinfo&) { + return &reinterpret_cast<char&>(deleter_); + } + + void* get_untyped_deleter() { + return &reinterpret_cast<char&>(deleter_); + } + +private: + deleter_type deleter_; + A allocator_; +}; + +#if !defined(BOOST_NO_CXX11_ALLOCATOR) +template<class P, class T, class U, class A> +class sp_counted_impl_pda<P, sp_array_destroyer<T, U>, + sp_array_allocator<T, A> > + : public sp_counted_base { +public: + typedef sp_array_destroyer<T, U> deleter_type; + typedef sp_array_allocator<T, A> allocator_type; + +private: + typedef sp_counted_impl_pda<P, deleter_type, allocator_type> type; + typedef sp_array_allocator<T, + typename sp_bind_allocator<A, type>::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() { + deallocator allocator(deleter_.allocator(), deleter_.size()); + this->~type(); + allocator.deallocate(this, 1); + } + + void* get_deleter(const sp_typeinfo&) { + return &reinterpret_cast<char&>(deleter_); + } + + void* get_untyped_deleter() { + return &reinterpret_cast<char&>(deleter_); } + +private: + deleter_type deleter_; +}; +#endif + +} /* detail */ + +template<class T, class A> +inline typename detail::sp_if_size_array<T>::type +allocate_shared(const A& allocator) +{ + typedef typename detail::sp_array_element<T>::type type; + typedef typename detail::sp_array_scalar<T>::type scalar; + typedef typename detail::sp_select_size_deleter<A, scalar, + detail::sp_array_count<T>::value>::type deleter; + shared_ptr<T> result(static_cast<type*>(0), + detail::sp_inplace_tag<deleter>(), allocator); + deleter* state = detail::sp_get_deleter<deleter>(result); + void* start = state->construct(); + return shared_ptr<T>(result, static_cast<type*>(start)); +} + +template<class T, class A> +inline typename detail::sp_if_size_array<T>::type +allocate_shared(const A& allocator, + const typename detail::sp_array_element<T>::type& value) +{ + typedef typename detail::sp_array_element<T>::type type; + typedef typename detail::sp_array_scalar<T>::type scalar; + typedef typename detail::sp_select_size_deleter<A, scalar, + detail::sp_array_count<T>::value>::type deleter; + shared_ptr<T> result(static_cast<type*>(0), + detail::sp_inplace_tag<deleter>(), allocator); + deleter* state = detail::sp_get_deleter<deleter>(result); + void* start = state->construct(reinterpret_cast<const + scalar*>(&value), detail::sp_array_count<type>::value); + return shared_ptr<T>(result, static_cast<type*>(start)); +} + +template<class T, class A> +inline typename detail::sp_if_size_array<T>::type +allocate_shared_noinit(const A& allocator) +{ + typedef typename detail::sp_array_element<T>::type type; + typedef typename detail::sp_array_scalar<T>::type scalar; + typedef detail::sp_size_array_deleter<scalar, + detail::sp_array_count<T>::value> deleter; + shared_ptr<T> result(static_cast<type*>(0), + detail::sp_inplace_tag<deleter>(), allocator); + deleter* state = detail::sp_get_deleter<deleter>(result); + void* start = state->construct_default(); + return shared_ptr<T>(result, static_cast<type*>(start)); } +template<class T, class A> +inline typename detail::sp_if_array<T>::type +allocate_shared(const A& allocator, std::size_t count) +{ + typedef typename detail::sp_array_element<T>::type type; + typedef typename detail::sp_array_scalar<T>::type scalar; + typedef typename detail::sp_select_deleter<A, scalar>::type deleter; + std::size_t size = count * detail::sp_array_count<type>::value; + void* start; + shared_ptr<T> result(static_cast<type*>(0), + detail::sp_inplace_tag<deleter>(), + detail::sp_array_allocator<scalar, A>(allocator, size, &start)); + deleter* state = detail::sp_get_deleter<deleter>(result); + state->construct(static_cast<scalar*>(start)); + return shared_ptr<T>(result, static_cast<type*>(start)); +} + +template<class T, class A> +inline typename detail::sp_if_array<T>::type +allocate_shared(const A& allocator, std::size_t count, + const typename detail::sp_array_element<T>::type& value) +{ + typedef typename detail::sp_array_element<T>::type type; + typedef typename detail::sp_array_scalar<T>::type scalar; + typedef typename detail::sp_select_deleter<A, scalar>::type deleter; + std::size_t size = count * detail::sp_array_count<type>::value; + void* start; + shared_ptr<T> result(static_cast<type*>(0), + detail::sp_inplace_tag<deleter>(), + detail::sp_array_allocator<scalar, A>(allocator, size, &start)); + deleter* state = detail::sp_get_deleter<deleter>(result); + state->construct(static_cast<scalar*>(start), + reinterpret_cast<const scalar*>(&value), + detail::sp_array_count<type>::value); + return shared_ptr<T>(result, static_cast<type*>(start)); +} + +template<class T, class A> +inline typename detail::sp_if_array<T>::type +allocate_shared_noinit(const A& allocator, std::size_t count) +{ + typedef typename detail::sp_array_element<T>::type type; + typedef typename detail::sp_array_scalar<T>::type scalar; + typedef detail::sp_array_deleter<scalar> deleter; + std::size_t size = count * detail::sp_array_count<type>::value; + void* start; + shared_ptr<T> result(static_cast<type*>(0), + detail::sp_inplace_tag<deleter>(), + detail::sp_array_allocator<scalar, A>(allocator, size, &start)); + deleter* state = detail::sp_get_deleter<deleter>(result); + state->construct_default(static_cast<scalar*>(start)); + return shared_ptr<T>(result, static_cast<type*>(start)); +} + +} /* boost */ + #endif |