123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179 |
- /*
- Copyright 2017-2019 Glen Joseph Fernandes
- ([email protected])
- 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 <boost/smart_ptr/detail/requires_cxx11.hpp>
- #include <boost/smart_ptr/allocate_shared_array.hpp>
- #include <boost/smart_ptr/local_shared_ptr.hpp>
- 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);
- }
- void local_cb_destroy() BOOST_SP_NOEXCEPT BOOST_OVERRIDE {
- shared_count().swap(count_);
- }
- shared_count local_cb_get_shared_count() const
- BOOST_SP_NOEXCEPT BOOST_OVERRIDE {
- return count_;
- }
- private:
- shared_count count_;
- };
- template<class A>
- class lsp_array_state
- : public sp_array_state<A> {
- public:
- template<class U>
- lsp_array_state(const U& other, std::size_t size) BOOST_SP_NOEXCEPT
- : sp_array_state<A>(other, size) { }
- lsp_array_base& base() BOOST_SP_NOEXCEPT {
- return base_;
- }
- private:
- lsp_array_base base_;
- };
- template<class A, std::size_t N>
- class lsp_size_array_state
- : public sp_size_array_state<A, N> {
- public:
- template<class U>
- lsp_size_array_state(const U& other, std::size_t size) BOOST_SP_NOEXCEPT
- : sp_size_array_state<A, N>(other, size) { }
- lsp_array_base& base() BOOST_SP_NOEXCEPT {
- return base_;
- }
- private:
- lsp_array_base base_;
- };
- } /* detail */
- template<class T, class A>
- inline typename enable_if_<is_unbounded_array<T>::value,
- local_shared_ptr<T> >::type
- allocate_local_shared(const A& allocator, std::size_t count)
- {
- typedef typename detail::sp_array_element<T>::type element;
- typedef typename allocator_rebind<A, element>::type other;
- typedef detail::lsp_array_state<other> state;
- typedef detail::sp_array_base<state> base;
- detail::sp_array_result<other, base> result(allocator, count);
- base* node = result.get();
- element* start = detail::sp_array_start<element>(node);
- ::new(static_cast<void*>(node)) base(allocator, start, count);
- detail::lsp_array_base& local = node->state().base();
- local.set(node);
- result.release();
- return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
- &local);
- }
- template<class T, class A>
- inline typename enable_if_<is_bounded_array<T>::value,
- local_shared_ptr<T> >::type
- allocate_local_shared(const A& allocator)
- {
- enum {
- count = extent<T>::value
- };
- typedef typename detail::sp_array_element<T>::type element;
- typedef typename allocator_rebind<A, element>::type other;
- typedef detail::lsp_size_array_state<other, count> state;
- typedef detail::sp_array_base<state> base;
- detail::sp_array_result<other, base> result(allocator, count);
- base* node = result.get();
- element* start = detail::sp_array_start<element>(node);
- ::new(static_cast<void*>(node)) base(allocator, start, count);
- detail::lsp_array_base& local = node->state().base();
- local.set(node);
- result.release();
- return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
- &local);
- }
- template<class T, class A>
- inline typename enable_if_<is_unbounded_array<T>::value,
- local_shared_ptr<T> >::type
- allocate_local_shared(const A& allocator, std::size_t count,
- const typename remove_extent<T>::type& value)
- {
- typedef typename detail::sp_array_element<T>::type element;
- typedef typename allocator_rebind<A, element>::type other;
- typedef detail::lsp_array_state<other> state;
- typedef detail::sp_array_base<state> base;
- detail::sp_array_result<other, base> result(allocator, count);
- base* node = result.get();
- element* start = detail::sp_array_start<element>(node);
- ::new(static_cast<void*>(node)) base(allocator, start, count, value);
- detail::lsp_array_base& local = node->state().base();
- local.set(node);
- result.release();
- return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
- &local);
- }
- template<class T, class A>
- inline typename enable_if_<is_bounded_array<T>::value,
- local_shared_ptr<T> >::type
- allocate_local_shared(const A& allocator,
- const typename remove_extent<T>::type& value)
- {
- enum {
- count = extent<T>::value
- };
- typedef typename detail::sp_array_element<T>::type element;
- typedef typename allocator_rebind<A, element>::type other;
- typedef detail::lsp_size_array_state<other, count> state;
- typedef detail::sp_array_base<state> base;
- detail::sp_array_result<other, base> result(allocator, count);
- base* node = result.get();
- element* start = detail::sp_array_start<element>(node);
- ::new(static_cast<void*>(node)) base(allocator, start, count, value);
- detail::lsp_array_base& local = node->state().base();
- local.set(node);
- result.release();
- return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
- &local);
- }
- template<class T, class A>
- inline typename enable_if_<is_unbounded_array<T>::value,
- local_shared_ptr<T> >::type
- allocate_local_shared_noinit(const A& allocator, std::size_t count)
- {
- return boost::allocate_local_shared<T>(boost::noinit_adapt(allocator),
- count);
- }
- template<class T, class A>
- inline typename enable_if_<is_bounded_array<T>::value,
- local_shared_ptr<T> >::type
- allocate_local_shared_noinit(const A& allocator)
- {
- return boost::allocate_local_shared<T>(boost::noinit_adapt(allocator));
- }
- } /* boost */
- #endif
|