/* Copyright 2017-2019 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_LOCAL_SHARED_ARRAY_HPP #define BOOST_SMART_PTR_ALLOCATE_LOCAL_SHARED_ARRAY_HPP #include #include namespace boost { namespace detail { class BOOST_SYMBOL_VISIBLE lsp_array_base : public local_counted_base { public: void set(sp_counted_base* base) BOOST_SP_NOEXCEPT { count_ = shared_count(base); } virtual void local_cb_destroy() BOOST_SP_NOEXCEPT { shared_count().swap(count_); } virtual shared_count local_cb_get_shared_count() const BOOST_SP_NOEXCEPT { return count_; } private: shared_count count_; }; template class lsp_array_state : public sp_array_state { public: template lsp_array_state(const U& other, std::size_t size) BOOST_SP_NOEXCEPT : sp_array_state(other, size) { } lsp_array_base& base() BOOST_SP_NOEXCEPT { return base_; } private: lsp_array_base base_; }; template class lsp_size_array_state : public sp_size_array_state { public: template lsp_size_array_state(const U& other, std::size_t size) BOOST_SP_NOEXCEPT : sp_size_array_state(other, size) { } lsp_array_base& base() BOOST_SP_NOEXCEPT { return base_; } private: lsp_array_base base_; }; } /* detail */ template inline typename enable_if_::value, local_shared_ptr >::type allocate_local_shared(const A& allocator, std::size_t count) { typedef typename detail::sp_array_element::type element; typedef typename detail::sp_bind_allocator::type other; typedef detail::lsp_array_state state; typedef detail::sp_array_base base; detail::sp_array_result result(allocator, count); base* node = result.get(); element* start = detail::sp_array_start(node); ::new(static_cast(node)) base(allocator, start, count); detail::lsp_array_base& local = node->state().base(); local.set(node); result.release(); return local_shared_ptr(detail::lsp_internal_constructor_tag(), start, &local); } template inline typename enable_if_::value, local_shared_ptr >::type allocate_local_shared(const A& allocator) { enum { count = extent::value }; typedef typename detail::sp_array_element::type element; typedef typename detail::sp_bind_allocator::type other; typedef detail::lsp_size_array_state state; typedef detail::sp_array_base base; detail::sp_array_result result(allocator, count); base* node = result.get(); element* start = detail::sp_array_start(node); ::new(static_cast(node)) base(allocator, start, count); detail::lsp_array_base& local = node->state().base(); local.set(node); result.release(); return local_shared_ptr(detail::lsp_internal_constructor_tag(), start, &local); } template inline typename enable_if_::value, local_shared_ptr >::type allocate_local_shared(const A& allocator, std::size_t count, const typename remove_extent::type& value) { typedef typename detail::sp_array_element::type element; typedef typename detail::sp_bind_allocator::type other; typedef detail::lsp_array_state state; typedef detail::sp_array_base base; detail::sp_array_result result(allocator, count); base* node = result.get(); element* start = detail::sp_array_start(node); ::new(static_cast(node)) base(allocator, start, count, value); detail::lsp_array_base& local = node->state().base(); local.set(node); result.release(); return local_shared_ptr(detail::lsp_internal_constructor_tag(), start, &local); } template inline typename enable_if_::value, local_shared_ptr >::type allocate_local_shared(const A& allocator, const typename remove_extent::type& value) { enum { count = extent::value }; typedef typename detail::sp_array_element::type element; typedef typename detail::sp_bind_allocator::type other; typedef detail::lsp_size_array_state state; typedef detail::sp_array_base base; detail::sp_array_result result(allocator, count); base* node = result.get(); element* start = detail::sp_array_start(node); ::new(static_cast(node)) base(allocator, start, count, value); detail::lsp_array_base& local = node->state().base(); local.set(node); result.release(); return local_shared_ptr(detail::lsp_internal_constructor_tag(), start, &local); } template inline typename enable_if_::value, local_shared_ptr >::type allocate_local_shared_noinit(const A& allocator, std::size_t count) { return boost::allocate_local_shared(boost::noinit_adapt(allocator), count); } template inline typename enable_if_::value, local_shared_ptr >::type allocate_local_shared_noinit(const A& allocator) { return boost::allocate_local_shared(boost::noinit_adapt(allocator)); } } /* boost */ #endif