diff options
Diffstat (limited to 'boost/smart_ptr/allocate_shared_array.hpp')
-rw-r--r-- | boost/smart_ptr/allocate_shared_array.hpp | 983 |
1 files changed, 327 insertions, 656 deletions
diff --git a/boost/smart_ptr/allocate_shared_array.hpp b/boost/smart_ptr/allocate_shared_array.hpp index b43b43d575..23c35aff3f 100644 --- a/boost/smart_ptr/allocate_shared_array.hpp +++ b/boost/smart_ptr/allocate_shared_array.hpp @@ -9,9 +9,10 @@ Distributed under the Boost Software License, Version 1.0. #define BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP #include <boost/smart_ptr/shared_ptr.hpp> +#include <boost/type_traits/alignment_of.hpp> +#include <boost/type_traits/has_trivial_assign.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 { @@ -105,37 +106,24 @@ struct sp_array_count<T[N]> { }; }; -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 }; }; template<std::size_t N, std::size_t M> -struct sp_max_size { +struct sp_align_up { enum { - value = N < M ? M : N + value = (N + M - 1) & ~(M - 1) }; }; #if !defined(BOOST_NO_CXX11_ALLOCATOR) template<class A, class T> struct sp_bind_allocator { - typedef typename std::allocator_traits<A>::template - rebind_alloc<T> type; + typedef typename std::allocator_traits<A>::template rebind_alloc<T> type; }; #else template<class A, class T> @@ -144,6 +132,13 @@ struct sp_bind_allocator { }; #endif +template<class T> +BOOST_CONSTEXPR inline std::size_t +sp_objects(std::size_t size) BOOST_SP_NOEXCEPT +{ + return (size + sizeof(T) - 1) / sizeof(T); +} + template<bool, class = void> struct sp_enable { }; @@ -152,873 +147,549 @@ 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<bool E, class A, class T> +inline typename sp_enable<!E && boost::has_trivial_destructor<T>::value>::type +sp_array_destroy(A&, T*, std::size_t) BOOST_SP_NOEXCEPT { } -template<class T> -inline -typename sp_enable<!boost::has_trivial_destructor<T>::value>::type -sp_array_destroy(T* storage, std::size_t size) +template<bool E, class A, class T> +inline typename sp_enable<!E && + !boost::has_trivial_destructor<T>::value>::type +sp_array_destroy(A&, T* start, std::size_t size) { while (size > 0) { - storage[--size].~T(); + start[--size].~T(); } } #if !defined(BOOST_NO_CXX11_ALLOCATOR) -template<class A, class T> -inline void -sp_array_destroy(A& allocator, T* storage, std::size_t size) +template<bool E, class A, class T> +inline typename sp_enable<E>::type +sp_array_destroy(A& allocator, T* start, std::size_t size) { while (size > 0) { - std::allocator_traits<A>::destroy(allocator, &storage[--size]); + std::allocator_traits<A>::destroy(allocator, start + --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) +template<bool E, class A, class T> +inline typename sp_enable<!E && + boost::has_trivial_constructor<T>::value && + boost::has_trivial_assign<T>::value>::type +sp_array_construct(A&, T* start, std::size_t size) { for (std::size_t i = 0; i < size; ++i) { - ::new(static_cast<void*>(storage + i)) T(); + start[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) +template<bool E, class A, class T> +inline typename sp_enable<!E && + boost::has_trivial_constructor<T>::value && + boost::has_trivial_assign<T>::value>::type +sp_array_construct(A&, T* start, std::size_t size, const T* list, + std::size_t count) +{ + for (std::size_t i = 0; i < size; ++i) { + start[i] = list[i % count]; + } +} + +#if !defined(BOOST_NO_EXCEPTIONS) +template<bool E, class A, class T> +inline typename sp_enable<!E && + !(boost::has_trivial_constructor<T>::value && + boost::has_trivial_assign<T>::value)>::type +sp_array_construct(A& none, T* start, std::size_t size) { std::size_t i = 0; try { for (; i < size; ++i) { - ::new(static_cast<void*>(storage + i)) T(); + ::new(static_cast<void*>(start + i)) T(); } } catch (...) { - while (i > 0) { - storage[--i].~T(); - } + sp_array_destroy<E>(none, start, i); throw; } } -template<class T> -inline void -sp_array_construct(T* storage, std::size_t size, const T* list, +template<bool E, class A, class T> +inline typename sp_enable<!E && + !(boost::has_trivial_constructor<T>::value && + boost::has_trivial_assign<T>::value)>::type +sp_array_construct(A& none, T* start, 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]); + ::new(static_cast<void*>(start + i)) T(list[i % count]); } } catch (...) { - while (i > 0) { - storage[--i].~T(); - } + sp_array_destroy<E>(none, start, i); throw; } } #else -template<class T> -inline void -sp_array_construct(T* storage, std::size_t size) +template<bool E, class A, class T> +inline typename sp_enable<!E && + !(boost::has_trivial_constructor<T>::value && + boost::has_trivial_assign<T>::value)>::type +sp_array_construct(A&, T* start, std::size_t size) { for (std::size_t i = 0; i < size; ++i) { - ::new(static_cast<void*>(storage + i)) T(); + ::new(static_cast<void*>(start + i)) T(); } } -template<class T> -inline void -sp_array_construct(T* storage, std::size_t size, const T* list, +template<bool E, class A, class T> +inline typename sp_enable<!E && + !(boost::has_trivial_constructor<T>::value && + boost::has_trivial_assign<T>::value)>::type +sp_array_construct(A&, T* start, 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]); + ::new(static_cast<void*>(start + i)) T(list[i % count]); } } #endif #if !defined(BOOST_NO_CXX11_ALLOCATOR) #if !defined(BOOST_NO_EXCEPTIONS) -template<class A, class T> -inline void -sp_array_construct(A& allocator, T* storage, std::size_t size) +template<bool E, class A, class T> +inline typename sp_enable<E>::type +sp_array_construct(A& allocator, T* start, std::size_t size) { std::size_t i = 0; try { for (i = 0; i < size; ++i) { - std::allocator_traits<A>::construct(allocator, storage + i); + std::allocator_traits<A>::construct(allocator, start + i); } } catch (...) { - sp_array_destroy(allocator, storage, i); + sp_array_destroy<E>(allocator, start, 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) +template<bool E, class A, class T> +inline typename sp_enable<E>::type +sp_array_construct(A& allocator, T* start, 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, + std::allocator_traits<A>::construct(allocator, start + i, list[i % count]); } } catch (...) { - sp_array_destroy(allocator, storage, i); + sp_array_destroy<E>(allocator, start, i); throw; } } #else -template<class A, class T> -inline void -sp_array_construct(A& allocator, T* storage, std::size_t size) +template<bool E, class A, class T> +inline typename sp_enable<E>::type +sp_array_construct(A& allocator, T* start, std::size_t size) { for (std::size_t i = 0; i < size; ++i) { - std::allocator_traits<A>::construct(allocator, storage + i); + std::allocator_traits<A>::construct(allocator, start + 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) +template<bool E, class A, class T> +inline typename sp_enable<E>::type +sp_array_construct(A& allocator, T* start, 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, + std::allocator_traits<A>::construct(allocator, start + i, list[i % count]); } } #endif #endif -template<class T> -inline -typename sp_enable<boost::has_trivial_constructor<T>::value>::type -sp_array_default(T*, std::size_t) BOOST_NOEXCEPT { } +template<class A, class T> +inline typename sp_enable<boost::has_trivial_constructor<T>::value>::type +sp_array_default(A&, T*, std::size_t) BOOST_SP_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) +template<class A, class T> +inline typename sp_enable<!boost::has_trivial_constructor<T>::value>::type +sp_array_default(A& none, T* start, std::size_t size) { std::size_t i = 0; try { for (; i < size; ++i) { - ::new(static_cast<void*>(storage + i)) T; + ::new(static_cast<void*>(start + i)) T; } } catch (...) { - while (i > 0) { - storage[--i].~T(); - } + sp_array_destroy<false>(none, start, i); 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) +template<bool E, class A, class T> +inline typename sp_enable<!boost::has_trivial_constructor<T>::value>::type +sp_array_default(A&, T* start, std::size_t size) { for (std::size_t i = 0; i < size; ++i) { - ::new(static_cast<void*>(storage + i)) T; + ::new(static_cast<void*>(start + 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) -template<class T, std::size_t N, class A> -class sp_size_array_destroyer { +template<class A> +class sp_array_state { public: - template<class U> - static void operator_fn(U) BOOST_NOEXCEPT { } + typedef A type; template<class U> - sp_size_array_destroyer(const U& allocator) BOOST_NOEXCEPT + sp_array_state(const U& allocator, std::size_t size) BOOST_SP_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 { + A& allocator() BOOST_SP_NOEXCEPT { return allocator_; } - std::size_t size() const BOOST_NOEXCEPT { + std::size_t size() const BOOST_SP_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; +template<class A, std::size_t N> +class sp_size_array_state { 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) { } + typedef A type; 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); - } + sp_size_array_state(const U& allocator, std::size_t) BOOST_SP_NOEXCEPT + : allocator_(allocator) { } - 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 { + A& allocator() BOOST_SP_NOEXCEPT { return allocator_; } - std::size_t size() const BOOST_NOEXCEPT { - return size_; + BOOST_CONSTEXPR std::size_t size() const BOOST_SP_NOEXCEPT { + return N; } 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 A> +struct sp_use_construct { + enum { + value = true + }; }; -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 T> +struct sp_use_construct<std::allocator<T> > { + enum { + value = false + }; }; - -template<class A, class T> -struct sp_select_deleter { - typedef sp_array_destroyer<T, - typename sp_bind_allocator<A, T>::type> type; +#else +template<class> +struct sp_use_construct { + enum { + value = false + }; }; +#endif -template<class U, class T> -struct sp_select_deleter<std::allocator<U>, T> { - typedef sp_array_deleter<T> type; -}; -#else -template<class, class T, std::size_t N> -struct sp_select_size_deleter { - typedef sp_size_array_deleter<T, N> type; +template<class T, class U> +struct sp_array_alignment { + enum { + value = sp_max_size<boost::alignment_of<T>::value, + boost::alignment_of<U>::value>::value + }; }; -template<class, class T> -struct sp_select_deleter { - typedef sp_array_deleter<T> type; +template<class T, class U> +struct sp_array_offset { + enum { + value = sp_align_up<sizeof(T), sp_array_alignment<T, U>::value>::value + }; }; -#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; +template<class T, class U> +struct sp_array_storage { + enum { + value = sp_array_alignment<T, U>::value + }; + typedef typename boost::type_with_alignment<value>::type type; +}; -private: - typedef sp_counted_impl_pda<P, deleter_type, A> type; - typedef typename sp_bind_allocator<A, type>::type deallocator; +template<class T, class U> +inline U* +sp_array_start(void* base) BOOST_SP_NOEXCEPT +{ + enum { + size = sp_array_offset<T, U>::value + }; + return reinterpret_cast<U*>(static_cast<char*>(base) + size); +} -public: - sp_counted_impl_pda(P, const deleter_type&, const A& allocator) - : deleter_(allocator), - allocator_(allocator) { } +template<class A, class T> +class sp_array_creator { + typedef typename A::value_type scalar; - sp_counted_impl_pda(P, const A& allocator) - : deleter_(allocator) { } + enum { + offset = sp_array_offset<T, scalar>::value + }; - void dispose() { - deleter_(0); - } + typedef typename sp_array_storage<T, scalar>::type type; - void destroy() { - deallocator allocator(allocator_); - this->~type(); - allocator.deallocate(this, 1); - } +public: + template<class U> + sp_array_creator(const U& other, std::size_t size) BOOST_SP_NOEXCEPT + : other_(other), + size_(sp_objects<type>(offset + sizeof(scalar) * size)) { } - void* get_deleter(const sp_typeinfo&) { - return &reinterpret_cast<char&>(deleter_); + T* create() { + return reinterpret_cast<T*>(other_.allocate(size_)); } - void* get_untyped_deleter() { - return &reinterpret_cast<char&>(deleter_); + void destroy(T* base) { + other_.deallocate(reinterpret_cast<type*>(base), size_); } private: - deleter_type deleter_; - A allocator_; + typename sp_bind_allocator<A, type>::type other_; + std::size_t size_; }; -#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; +struct sp_default { }; -private: - typedef sp_counted_impl_pda<P, deleter_type, A> type; - typedef typename sp_bind_allocator<A, type>::type deallocator; +template<class T, bool E = sp_use_construct<T>::value> +class sp_array_base + : public sp_counted_base { + typedef typename T::type allocator; public: - sp_counted_impl_pda(P, const deleter_type&, const A& allocator) - : deleter_(allocator) { } - - sp_counted_impl_pda(P, const A& allocator) - : deleter_(allocator) { } + typedef typename allocator::value_type type; - void dispose() { - deleter_(0); + template<class A> + sp_array_base(const A& other, std::size_t size, type* start) + : state_(other, size) { + sp_array_construct<E>(state_.allocator(), start, state_.size()); } - void destroy() { - deallocator allocator(deleter_.allocator()); - this->~type(); - allocator.deallocate(this, 1); + template<class A> + sp_array_base(const A& other, std::size_t size, const type* list, + std::size_t count, type* start) + : state_(other, size) { + sp_array_construct<E>(state_.allocator(), start, state_.size(), list, + count); } - void* get_deleter(const sp_typeinfo&) { - return &reinterpret_cast<char&>(deleter_); + template<class A> + sp_array_base(sp_default, const A& other, std::size_t size, type* start) + : state_(other, size) { + sp_array_default(state_.allocator(), start, state_.size()); } - void* get_untyped_deleter() { - return &reinterpret_cast<char&>(deleter_); + T& state() BOOST_SP_NOEXCEPT { + return state_; } -private: - deleter_type deleter_; -}; -#endif - -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()) { } + virtual void dispose() { + sp_array_destroy<E>(state_.allocator(), + sp_array_start<sp_array_base, type>(this), state_.size()); + } - void dispose() { - deleter_(0); + virtual void destroy() { + sp_array_creator<allocator, sp_array_base> other(state_.allocator(), + state_.size()); + this->~sp_array_base(); + other.destroy(this); } - void destroy() { - deallocator allocator(allocator_, deleter_.size()); - this->~type(); - allocator.deallocate(this, 1); + virtual void* get_deleter(const sp_typeinfo&) { + return 0; } - void* get_deleter(const sp_typeinfo&) { - return &reinterpret_cast<char&>(deleter_); + virtual void* get_local_deleter(const sp_typeinfo&) { + return 0; } - void* get_untyped_deleter() { - return &reinterpret_cast<char&>(deleter_); + virtual void* get_untyped_deleter() { + return 0; } private: - deleter_type deleter_; - A allocator_; + T state_; }; -#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; - +template<class A, class T> +struct sp_array_result { 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); - } + template<class U> + sp_array_result(const U& other, std::size_t size) + : creator_(other, size), + result_(creator_.create()) { } - void destroy() { - deallocator allocator(deleter_.allocator(), deleter_.size()); - this->~type(); - allocator.deallocate(this, 1); + ~sp_array_result() { + if (result_) { + creator_.destroy(result_); + } } - void* get_deleter(const sp_typeinfo&) { - return &reinterpret_cast<char&>(deleter_); + T* get() const { + return result_; } - void* get_untyped_deleter() { - return &reinterpret_cast<char&>(deleter_); + void release() { + result_ = 0; } private: - deleter_type deleter_; + sp_array_result(const sp_array_result&); + sp_array_result& operator=(const sp_array_result&); + + sp_array_creator<A, T> creator_; + T* result_; }; -#endif } /* detail */ template<class T, class A> -inline typename detail::sp_if_size_array<T>::type -allocate_shared(const A& allocator) +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_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)); + typedef typename detail::sp_bind_allocator<A, scalar>::type other; + typedef detail::sp_array_state<other> state; + typedef detail::sp_array_base<state> base; + std::size_t size = count * detail::sp_array_count<type>::value; + detail::sp_array_result<other, base> result(allocator, size); + detail::sp_counted_base* node = result.get(); + scalar* start = detail::sp_array_start<base, scalar>(node); + ::new(static_cast<void*>(node)) base(allocator, size, start); + result.release(); + return shared_ptr<T>(detail::sp_internal_constructor_tag(), + reinterpret_cast<type*>(start), detail::shared_count(node)); } 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) +allocate_shared(const A& allocator) { + enum { + size = detail::sp_array_count<T>::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)); + typedef typename detail::sp_bind_allocator<A, scalar>::type other; + typedef detail::sp_size_array_state<other, size> state; + typedef detail::sp_array_base<state> base; + detail::sp_array_result<other, base> result(allocator, size); + detail::sp_counted_base* node = result.get(); + scalar* start = detail::sp_array_start<base, scalar>(node); + ::new(static_cast<void*>(node)) base(allocator, size, start); + result.release(); + return shared_ptr<T>(detail::sp_internal_constructor_tag(), + reinterpret_cast<type*>(start), detail::shared_count(node)); } template<class T, class A> -inline typename detail::sp_if_size_array<T>::type -allocate_shared_noinit(const A& allocator) +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 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)); + typedef typename detail::sp_bind_allocator<A, scalar>::type other; + typedef detail::sp_array_state<other> state; + typedef detail::sp_array_base<state> base; + std::size_t size = count * detail::sp_array_count<type>::value; + detail::sp_array_result<other, base> result(allocator, size); + detail::sp_counted_base* node = result.get(); + scalar* start = detail::sp_array_start<base, scalar>(node); + ::new(static_cast<void*>(node)) base(allocator, size, + reinterpret_cast<const scalar*>(&value), + detail::sp_array_count<type>::value, start); + result.release(); + return shared_ptr<T>(detail::sp_internal_constructor_tag(), + reinterpret_cast<type*>(start), detail::shared_count(node)); } template<class T, class A> -inline typename detail::sp_if_array<T>::type -allocate_shared(const A& allocator, std::size_t count) +inline typename detail::sp_if_size_array<T>::type +allocate_shared(const A& allocator, + const typename detail::sp_array_element<T>::type& value) { + enum { + size = detail::sp_array_count<T>::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)); - return shared_ptr<T>(result, static_cast<type*>(start)); + typedef typename detail::sp_bind_allocator<A, scalar>::type other; + typedef detail::sp_size_array_state<other, size> state; + typedef detail::sp_array_base<state> base; + detail::sp_array_result<other, base> result(allocator, size); + detail::sp_counted_base* node = result.get(); + scalar* start = detail::sp_array_start<base, scalar>(node); + ::new(static_cast<void*>(node)) base(allocator, size, + reinterpret_cast<const scalar*>(&value), + detail::sp_array_count<type>::value, start); + result.release(); + return shared_ptr<T>(detail::sp_internal_constructor_tag(), + reinterpret_cast<type*>(start), detail::shared_count(node)); } 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) +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 typename detail::sp_select_deleter<A, scalar>::type deleter; + typedef typename detail::sp_bind_allocator<A, scalar>::type other; + typedef detail::sp_array_state<other> state; + typedef detail::sp_array_base<state, false> base; 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)); + detail::sp_array_result<other, base> result(allocator, size); + detail::sp_counted_base* node = result.get(); + scalar* start = detail::sp_array_start<base, scalar>(node); + ::new(static_cast<void*>(node)) base(detail::sp_default(), allocator, + size, start); + result.release(); + return shared_ptr<T>(detail::sp_internal_constructor_tag(), + reinterpret_cast<type*>(start), detail::shared_count(node)); } template<class T, class A> -inline typename detail::sp_if_array<T>::type -allocate_shared_noinit(const A& allocator, std::size_t count) +inline typename detail::sp_if_size_array<T>::type +allocate_shared_noinit(const A& allocator) { + enum { + size = detail::sp_array_count<T>::value + }; 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)); + typedef typename detail::sp_bind_allocator<A, scalar>::type other; + typedef detail::sp_size_array_state<other, size> state; + typedef detail::sp_array_base<state, false> base; + detail::sp_array_result<other, base> result(allocator, size); + detail::sp_counted_base* node = result.get(); + scalar* start = detail::sp_array_start<base, scalar>(node); + ::new(static_cast<void*>(node)) base(detail::sp_default(), allocator, + size, start); + result.release(); + return shared_ptr<T>(detail::sp_internal_constructor_tag(), + reinterpret_cast<type*>(start), detail::shared_count(node)); } } /* boost */ |