/* Copyright 2017 Glen Joseph Fernandes (glenjofe@gmail.com) Distributed under the Boost Software License, Version 1.0. (http://www.boost.org/LICENSE_1_0.txt) */ #ifndef BOOST_SMART_PTR_ALLOCATE_LOCAL_SHARED_ARRAY_HPP #define BOOST_SMART_PTR_ALLOCATE_LOCAL_SHARED_ARRAY_HPP #include #include namespace boost { namespace detail { template struct lsp_if_array { }; template struct lsp_if_array { typedef boost::local_shared_ptr type; }; template struct lsp_if_size_array { }; template struct lsp_if_size_array { typedef boost::local_shared_ptr type; }; class 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 detail::lsp_if_array::type allocate_local_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_bind_allocator::type other; typedef detail::lsp_array_state state; typedef detail::sp_array_base base; std::size_t size = count * detail::sp_array_count::value; detail::sp_array_result result(allocator, size); base* node = result.get(); scalar* start = detail::sp_array_start(node); ::new(static_cast(node)) base(allocator, size, start); detail::lsp_array_base& local = node->state().base(); local.set(node); result.release(); return local_shared_ptr(detail::lsp_internal_constructor_tag(), reinterpret_cast(start), &local); } template inline typename detail::lsp_if_size_array::type allocate_local_shared(const A& allocator) { enum { size = detail::sp_array_count::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; typedef detail::lsp_size_array_state state; typedef detail::sp_array_base base; detail::sp_array_result result(allocator, size); base* node = result.get(); scalar* start = detail::sp_array_start(node); ::new(static_cast(node)) base(allocator, size, start); detail::lsp_array_base& local = node->state().base(); local.set(node); result.release(); return local_shared_ptr(detail::lsp_internal_constructor_tag(), reinterpret_cast(start), &local); } template inline typename detail::lsp_if_array::type allocate_local_shared(const A& allocator, std::size_t count, const typename detail::sp_array_element::type& value) { typedef typename detail::sp_array_element::type type; typedef typename detail::sp_array_scalar::type scalar; typedef typename detail::sp_bind_allocator::type other; typedef detail::lsp_array_state state; typedef detail::sp_array_base base; std::size_t size = count * detail::sp_array_count::value; detail::sp_array_result result(allocator, size); base* node = result.get(); scalar* start = detail::sp_array_start(node); ::new(static_cast(node)) base(allocator, size, reinterpret_cast(&value), detail::sp_array_count::value, start); detail::lsp_array_base& local = node->state().base(); local.set(node); result.release(); return local_shared_ptr(detail::lsp_internal_constructor_tag(), reinterpret_cast(start), &local); } template inline typename detail::lsp_if_size_array::type allocate_local_shared(const A& allocator, const typename detail::sp_array_element::type& value) { enum { size = detail::sp_array_count::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; typedef detail::lsp_size_array_state state; typedef detail::sp_array_base base; detail::sp_array_result result(allocator, size); base* node = result.get(); scalar* start = detail::sp_array_start(node); ::new(static_cast(node)) base(allocator, size, reinterpret_cast(&value), detail::sp_array_count::value, start); detail::lsp_array_base& local = node->state().base(); local.set(node); result.release(); return local_shared_ptr(detail::lsp_internal_constructor_tag(), reinterpret_cast(start), &local); } template inline typename detail::lsp_if_array::type allocate_local_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 typename detail::sp_bind_allocator::type other; typedef detail::lsp_array_state state; typedef detail::sp_array_base base; std::size_t size = count * detail::sp_array_count::value; detail::sp_array_result result(allocator, size); base* node = result.get(); scalar* start = detail::sp_array_start(node); ::new(static_cast(node)) base(detail::sp_default(), allocator, size, start); detail::lsp_array_base& local = node->state().base(); local.set(node); result.release(); return local_shared_ptr(detail::lsp_internal_constructor_tag(), reinterpret_cast(start), &local); } template inline typename detail::lsp_if_size_array::type allocate_local_shared_noinit(const A& allocator) { enum { size = detail::sp_array_count::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; typedef detail::lsp_size_array_state state; typedef detail::sp_array_base base; detail::sp_array_result result(allocator, size); base* node = result.get(); scalar* start = detail::sp_array_start(node); ::new(static_cast(node)) base(detail::sp_default(), allocator, size, start); detail::lsp_array_base& local = node->state().base(); local.set(node); result.release(); return local_shared_ptr(detail::lsp_internal_constructor_tag(), reinterpret_cast(start), &local); } } /* boost */ #endif