diff --git a/include/boost/smart_ptr/allocate_shared_array.hpp b/include/boost/smart_ptr/allocate_shared_array.hpp index 5857c47..0bd9b04 100644 --- a/include/boost/smart_ptr/allocate_shared_array.hpp +++ b/include/boost/smart_ptr/allocate_shared_array.hpp @@ -106,24 +106,6 @@ struct sp_array_count { }; }; -template -struct sp_array_count { }; - -template -inline D* -sp_get_deleter(const boost::shared_ptr& value) BOOST_NOEXCEPT_OR_NOTHROW -{ - 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 { enum { @@ -131,6 +113,13 @@ struct sp_max_size { }; }; +template +struct sp_align_up { + enum { + value = (N + M - 1) & ~(M - 1) + }; +}; + #if !defined(BOOST_NO_CXX11_ALLOCATOR) template struct sp_bind_allocator { @@ -143,6 +132,13 @@ struct sp_bind_allocator { }; #endif +template +BOOST_CONSTEXPR inline std::size_t +sp_objects(std::size_t size) BOOST_SP_NOEXCEPT +{ + return (size + sizeof(T) - 1) / sizeof(T); +} + template struct sp_enable { }; @@ -151,13 +147,14 @@ struct sp_enable { typedef T type; }; -template -inline typename sp_enable::value>::type -sp_array_destroy(T*, std::size_t) BOOST_SP_NOEXCEPT { } +template +inline typename sp_enable::value>::type +sp_array_destroy(A&, T*, std::size_t) BOOST_SP_NOEXCEPT { } -template -inline typename sp_enable::value>::type -sp_array_destroy(T* storage, std::size_t size) +template +inline typename sp_enable::value>::type +sp_array_destroy(A&, T* storage, std::size_t size) { while (size > 0) { storage[--size].~T(); @@ -165,8 +162,8 @@ sp_array_destroy(T* storage, std::size_t size) } #if !defined(BOOST_NO_CXX11_ALLOCATOR) -template -inline void +template +inline typename sp_enable::type sp_array_destroy(A& allocator, T* storage, std::size_t size) { while (size > 0) { @@ -176,20 +173,22 @@ sp_array_destroy(A& allocator, T* storage, std::size_t 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) +template +inline typename sp_enable::value || + boost::has_trivial_destructor::value)>::type +sp_array_construct(A&, 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 && +template +inline typename sp_enable::value && !boost::has_trivial_destructor::value>::type -sp_array_construct(T* storage, std::size_t size) +sp_array_construct(A& none, T* storage, std::size_t size) { std::size_t i = 0; try { @@ -197,15 +196,16 @@ sp_array_construct(T* storage, std::size_t size) ::new(static_cast(storage + i)) T(); } } catch (...) { - sp_array_destroy(storage, i); + sp_array_destroy(none, storage, i); throw; } } -template -inline typename sp_enable::value || - boost::has_trivial_destructor::value>::type -sp_array_construct(T* storage, std::size_t size, const T* list, +template +inline typename sp_enable::value || + boost::has_trivial_destructor::value)>::type +sp_array_construct(A&, T* storage, std::size_t size, const T* list, std::size_t count) { for (std::size_t i = 0; i < size; ++i) { @@ -213,10 +213,11 @@ sp_array_construct(T* storage, std::size_t size, const T* list, } } -template -inline typename sp_enable::value && +template +inline typename sp_enable::value && !boost::has_trivial_destructor::value>::type -sp_array_construct(T* storage, std::size_t size, const T* list, +sp_array_construct(A& none, T* storage, std::size_t size, const T* list, std::size_t count) { std::size_t i = 0; @@ -225,23 +226,23 @@ sp_array_construct(T* storage, std::size_t size, const T* list, ::new(static_cast(storage + i)) T(list[i % count]); } } catch (...) { - sp_array_destroy(storage, i); + sp_array_destroy(none, storage, i); throw; } } #else -template -inline void -sp_array_construct(T* storage, std::size_t size) +template +inline typename sp_enable::type +sp_array_construct(A&, 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, +template +inline typename sp_enable::type +sp_array_construct(A&, T* storage, std::size_t size, const T* list, std::size_t count) { for (std::size_t i = 0; i < size; ++i) { @@ -252,8 +253,8 @@ sp_array_construct(T* storage, std::size_t size, const T* list, #if !defined(BOOST_NO_CXX11_ALLOCATOR) #if !defined(BOOST_NO_EXCEPTIONS) -template -inline void +template +inline typename sp_enable::type sp_array_construct(A& allocator, T* storage, std::size_t size) { std::size_t i = 0; @@ -262,13 +263,13 @@ sp_array_construct(A& allocator, T* storage, std::size_t size) std::allocator_traits::construct(allocator, storage + i); } } catch (...) { - sp_array_destroy(allocator, storage, i); + sp_array_destroy(allocator, storage, i); throw; } } -template -inline void +template +inline typename sp_enable::type sp_array_construct(A& allocator, T* storage, std::size_t size, const T* list, std::size_t count) { @@ -279,13 +280,13 @@ sp_array_construct(A& allocator, T* storage, std::size_t size, list[i % count]); } } catch (...) { - sp_array_destroy(allocator, storage, i); + sp_array_destroy(allocator, storage, i); throw; } } #else -template -inline void +template +inline typename sp_enable::type sp_array_construct(A& allocator, T* storage, std::size_t size) { for (std::size_t i = 0; i < size; ++i) { @@ -293,8 +294,8 @@ sp_array_construct(A& allocator, T* storage, std::size_t size) } } -template -inline void +template +inline typename sp_enable::type sp_array_construct(A& allocator, T* storage, std::size_t size, const T* list, std::size_t count) { @@ -306,25 +307,25 @@ sp_array_construct(A& allocator, T* storage, std::size_t size, #endif #endif -template +template inline typename sp_enable::value>::type -sp_array_default(T*, std::size_t) BOOST_SP_NOEXCEPT { } +sp_array_default(A&, T*, std::size_t) BOOST_SP_NOEXCEPT { } #if !defined(BOOST_NO_EXCEPTIONS) -template +template inline typename sp_enable::value && boost::has_trivial_destructor::value>::type -sp_array_default(T* storage, std::size_t size) +sp_array_default(A&, T* storage, std::size_t size) { for (std::size_t i = 0; i < size; ++i) { ::new(static_cast(storage + i)) T; } } -template +template inline typename sp_enable::value && !boost::has_trivial_destructor::value>::type -sp_array_default(T* storage, std::size_t size) +sp_array_default(A& none, T* storage, std::size_t size) { std::size_t i = 0; try { @@ -332,14 +333,14 @@ sp_array_default(T* storage, std::size_t size) ::new(static_cast(storage + i)) T; } } catch (...) { - sp_array_destroy(storage, i); + sp_array_destroy(none, storage, i); throw; } } #else -template +template inline typename sp_enable::value>::type -sp_array_default(T* storage, std::size_t size) +sp_array_default(A&, T* storage, std::size_t size) { for (std::size_t i = 0; i < size; ++i) { ::new(static_cast(storage + i)) T; @@ -347,650 +348,260 @@ sp_array_default(T* storage, std::size_t size) } #endif -template -struct sp_less_align { +template +class sp_array_state { +public: + typedef A type; + + sp_array_state(const A& allocator, std::size_t size) BOOST_SP_NOEXCEPT + : allocator_(allocator), + size_(size) { } + + A& allocator() BOOST_SP_NOEXCEPT { + return allocator_; + } + + std::size_t size() const BOOST_SP_NOEXCEPT { + return size_; + } + +private: + A allocator_; + std::size_t size_; +}; + +template +class sp_size_array_state { +public: + typedef A type; + + sp_size_array_state(const A& allocator, std::size_t) BOOST_SP_NOEXCEPT + : allocator_(allocator) { } + + A& allocator() BOOST_SP_NOEXCEPT { + return allocator_; + } + + BOOST_CONSTEXPR std::size_t size() const BOOST_SP_NOEXCEPT { + return N; + } + +private: + A allocator_; +}; + +#if !defined(BOOST_NO_CXX11_ALLOCATOR) +template +struct sp_use_construct { enum { - value = (boost::alignment_of::value) < N + value = true }; }; -template -BOOST_CONSTEXPR -inline typename sp_enable::value, std::size_t>::type -sp_align(std::size_t size) BOOST_SP_NOEXCEPT -{ - return (sizeof(T) * size + N - 1) & ~(N - 1); -} - -template -BOOST_CONSTEXPR -inline typename sp_enable::value, std::size_t>::type -sp_align(std::size_t size) BOOST_SP_NOEXCEPT -{ - return sizeof(T) * size; -} - template -BOOST_CONSTEXPR inline std::size_t -sp_types(std::size_t size) BOOST_SP_NOEXCEPT -{ - return (size + sizeof(T) - 1) / sizeof(T); -} - -template -class sp_size_array_deleter { -public: - template - static void operator_fn(U) BOOST_SP_NOEXCEPT { } - - sp_size_array_deleter() BOOST_SP_NOEXCEPT - : enabled_(false) { } - - template - sp_size_array_deleter(const A&) BOOST_SP_NOEXCEPT - : enabled_(false) { } - - sp_size_array_deleter(const sp_size_array_deleter&) BOOST_SP_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_SP_NOEXCEPT { } - - template - sp_size_array_destroyer(const U& allocator) BOOST_SP_NOEXCEPT - : allocator_(allocator), - enabled_(false) { } - - sp_size_array_destroyer(const sp_size_array_destroyer& other) - BOOST_SP_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_SP_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_SP_NOEXCEPT { } - - sp_array_deleter(std::size_t size) BOOST_SP_NOEXCEPT - : address_(0), - size_(size) { } - - template - sp_array_deleter(const A& allocator) BOOST_SP_NOEXCEPT - : address_(0), - size_(allocator.size()) { } - - template - sp_array_deleter(const A&, std::size_t size) BOOST_SP_NOEXCEPT - : address_(0), - size_(size) { } - - sp_array_deleter(const sp_array_deleter& other) BOOST_SP_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_SP_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_SP_NOEXCEPT { } - - template - sp_array_destroyer(const U& allocator, std::size_t size) BOOST_SP_NOEXCEPT - : allocator_(allocator), - size_(size), - address_(0) { } - - template - sp_array_destroyer(const U& allocator) BOOST_SP_NOEXCEPT - : allocator_(allocator.allocator()), - size_(allocator.size()), - address_(0) { } - - sp_array_destroyer(const sp_array_destroyer& other) BOOST_SP_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_SP_NOEXCEPT { - return allocator_; - } - - std::size_t size() const BOOST_SP_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: +struct sp_use_construct > { enum { - alignment = sp_max_size::value, - boost::alignment_of::value>::value + value = false + }; +}; +#else +template +struct sp_use_construct { + enum { + value = false + }; +}; +#endif + +template +struct sp_array_alignment { + enum { + value = sp_max_size::value, + boost::alignment_of::value>::value + }; +}; + +template +struct sp_array_offset { + enum { + value = sp_align_up::value>::value + }; +}; + +template +inline T* +sp_array_start(U* base) BOOST_SP_NOEXCEPT +{ + enum { + size = sp_array_offset::value + }; + return reinterpret_cast(reinterpret_cast(base) + size); +} + +template +class sp_array_creator { + typedef typename A::value_type scalar; + + enum { + alignment = sp_array_alignment::value + }; + enum { + offset = sp_array_offset::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_creator(const U& other, std::size_t size) BOOST_SP_NOEXCEPT + : other_(other), + size_(sp_objects(offset + sizeof(scalar) * size)) { } - sp_array_allocator(const A& allocator, std::size_t size, void** result) - BOOST_SP_NOEXCEPT - : allocator_(allocator), - size_(size), - result_(result) { } - - sp_array_allocator(const A& allocator, std::size_t size) BOOST_SP_NOEXCEPT - : allocator_(allocator), - size_(size) { } - - template - sp_array_allocator(const sp_array_allocator& other) - BOOST_SP_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(count); - std::size_t size = sp_types(node + sizeof(T) * size_); - type* address = allocator.allocate(size); - *result_ = reinterpret_cast(address) + node; - return reinterpret_cast(address); + T* create() { + return reinterpret_cast(other_.allocate(size_)); } - void deallocate(value_type* value, std::size_t count) { - type_allocator allocator(allocator_); - std::size_t node = sp_align(count); - std::size_t size = sp_types(node + sizeof(T) * size_); - allocator.deallocate(reinterpret_cast(value), size); - } - - const A& allocator() const BOOST_SP_NOEXCEPT { - return allocator_; - } - - std::size_t size() const BOOST_SP_NOEXCEPT { - return size_; + void destroy(T* base) { + other_.deallocate(reinterpret_cast(base), size_); } private: - A allocator_; + typename sp_bind_allocator::type other_; std::size_t size_; - void** result_; }; -template -inline bool -operator==(const sp_array_allocator& first, - const sp_array_allocator& second) BOOST_SP_NOEXCEPT -{ - return first.allocator() == second.allocator() && - first.size() == second.size(); -} +struct sp_default { }; -template -inline bool -operator!=(const sp_array_allocator& first, - const sp_array_allocator& second) BOOST_SP_NOEXCEPT -{ - return !(first == second); -} +template::value> +class sp_array_base + : public sp_counted_base { + typedef typename T::type allocator; -#if !defined(BOOST_NO_CXX11_ALLOCATOR) -template -struct sp_select_size_deleter { - typedef sp_size_array_destroyer::type> type; -}; +public: + typedef typename allocator::value_type type; -template -struct sp_select_size_deleter, T, N> { - typedef sp_size_array_deleter type; + template + sp_array_base(const A& other, std::size_t size) + : state_(other, size) { + sp_array_construct(state_.allocator(), sp_array_start(this), + state_.size()); + } + + template + sp_array_base(const A& other, std::size_t size, const type* list, + std::size_t count) + : state_(other, size) { + sp_array_construct(state_.allocator(), sp_array_start(this), + state_.size(), list, count); + } + + template + sp_array_base(sp_default, const A& other, std::size_t size) + : state_(other, size) { + sp_array_default(state_.allocator(), sp_array_start(this), + state_.size()); + } + + virtual void dispose() { + sp_array_destroy(state_.allocator(), sp_array_start(this), + state_.size()); + } + + virtual void destroy() { + sp_array_creator other(state_.allocator(), + state_.size()); + this->~sp_array_base(); + other.destroy(this); + } + + virtual void* get_deleter(const sp_typeinfo&) { + return 0; + } + + virtual void* get_local_deleter(const sp_typeinfo&) { + return 0; + } + + virtual void* get_untyped_deleter() { + return 0; + } + +private: + T state_; }; 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 { +struct sp_array_result { public: - typedef sp_size_array_deleter deleter_type; + template + sp_array_result(const U& other, std::size_t size) + : creator_(other, size), + result_(creator_.create()) { } -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); + ~sp_array_result() { + if (result_) { + creator_.destroy(result_); + } } - void destroy() { - deallocator allocator(allocator_); - this->~type(); - allocator.deallocate(this, 1); + T* get() const { + return result_; } - void* get_deleter(const sp_typeinfo& info) { - return info == BOOST_SP_TYPEID(deleter_type) ? - &reinterpret_cast(deleter_) : 0; - } - - void* get_local_deleter(const sp_typeinfo&) { - return 0; - } - - void* get_untyped_deleter() { - return &reinterpret_cast(deleter_); + T* release() { + T* value = result_; + result_ = 0; + return value; } private: - deleter_type deleter_; - A allocator_; + sp_array_result(const sp_array_result&); + sp_array_result& operator=(const sp_array_result&); + + sp_array_creator creator_; + T* result_; }; -#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() { - deallocator allocator(deleter_.allocator()); - this->~type(); - allocator.deallocate(this, 1); - } - - void* get_deleter(const sp_typeinfo& info) { - return info == BOOST_SP_TYPEID(deleter_type) ? - &reinterpret_cast(deleter_) : 0; - } - - void* get_local_deleter(const sp_typeinfo&) { - return 0; - } - - 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() { - deallocator allocator(allocator_, deleter_.size()); - this->~type(); - allocator.deallocate(this, 1); - } - - void* get_deleter(const sp_typeinfo& info) { - return info == BOOST_SP_TYPEID(deleter_type) ? - &reinterpret_cast(deleter_) : 0; - } - - void* get_local_deleter(const sp_typeinfo&) { - return 0; - } - - 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() { - deallocator allocator(deleter_.allocator(), deleter_.size()); - this->~type(); - allocator.deallocate(this, 1); - } - - void* get_deleter(const sp_typeinfo& info) { - return info == BOOST_SP_TYPEID(deleter_type) ? - &reinterpret_cast(deleter_) : 0; - } - - void* get_local_deleter(const sp_typeinfo&) { - return 0; - } - - 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; + typedef typename detail::sp_bind_allocator::type other; + typedef detail::sp_array_state state; + typedef detail::sp_array_base base; 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)); + detail::sp_array_result result(allocator, size); + base* node = result.get(); + ::new(static_cast(node)) base(allocator, size); + void* start = detail::sp_array_start(node); + detail::sp_counted_base* next = result.release(); + return shared_ptr(detail::sp_internal_constructor_tag(), + static_cast(start), detail::shared_count(next)); +} + +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_bind_allocator::type other; + enum { + size = detail::sp_array_count::value + }; + typedef detail::sp_size_array_state state; + typedef detail::sp_array_base base; + detail::sp_array_result result(allocator, size); + base* node = result.get(); + ::new(static_cast(node)) base(allocator, size); + void* start = detail::sp_array_start(node); + detail::sp_counted_base* next = result.release(); + return shared_ptr(detail::sp_internal_constructor_tag(), + static_cast(start), detail::shared_count(next)); } template @@ -1000,17 +611,43 @@ 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; + typedef typename detail::sp_bind_allocator::type other; + typedef detail::sp_array_state state; + typedef detail::sp_array_base base; 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), + detail::sp_array_result result(allocator, size); + base* node = result.get(); + ::new(static_cast(node)) base(allocator, size, reinterpret_cast(&value), detail::sp_array_count::value); - return shared_ptr(result, static_cast(start)); + void* start = detail::sp_array_start(node); + detail::sp_counted_base* next = result.release(); + return shared_ptr(detail::sp_internal_constructor_tag(), + static_cast(start), detail::shared_count(next)); +} + +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_bind_allocator::type other; + enum { + size = detail::sp_array_count::value + }; + typedef detail::sp_size_array_state state; + typedef detail::sp_array_base base; + detail::sp_array_result result(allocator, size); + base* node = result.get(); + ::new(static_cast(node)) base(allocator, size, + reinterpret_cast(&value), + detail::sp_array_count::value); + void* start = detail::sp_array_start(node); + detail::sp_counted_base* next = result.release(); + return shared_ptr(detail::sp_internal_constructor_tag(), + static_cast(start), detail::shared_count(next)); } template @@ -1019,15 +656,40 @@ 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; + typedef typename detail::sp_bind_allocator::type other; + typedef detail::sp_array_state state; + typedef detail::sp_array_base base; 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)); + detail::sp_array_result result(allocator, size); + base* node = result.get(); + ::new(static_cast(node)) base(detail::sp_default(), + allocator, size); + void* start = detail::sp_array_start(node); + detail::sp_counted_base* next = result.release(); + return shared_ptr(detail::sp_internal_constructor_tag(), + static_cast(start), detail::shared_count(next)); +} + +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 typename detail::sp_bind_allocator::type other; + enum { + size = detail::sp_array_count::value + }; + typedef detail::sp_size_array_state state; + typedef detail::sp_array_base base; + detail::sp_array_result result(allocator, size); + base* node = result.get(); + ::new(static_cast(node)) base(detail::sp_default(), + allocator, size); + void* start = detail::sp_array_start(node); + detail::sp_counted_base* next = result.release(); + return shared_ptr(detail::sp_internal_constructor_tag(), + static_cast(start), detail::shared_count(next)); } } /* boost */