File indexing completed on 2025-09-17 08:50:36
0001
0002
0003
0004
0005
0006
0007
0008 #ifndef BOOST_SMART_PTR_ALLOCATE_LOCAL_SHARED_ARRAY_HPP
0009 #define BOOST_SMART_PTR_ALLOCATE_LOCAL_SHARED_ARRAY_HPP
0010
0011 #include <boost/smart_ptr/allocate_shared_array.hpp>
0012 #include <boost/smart_ptr/local_shared_ptr.hpp>
0013 #include <boost/smart_ptr/detail/sp_type_traits.hpp>
0014 #include <type_traits>
0015
0016 namespace boost {
0017 namespace detail {
0018
0019 class BOOST_SYMBOL_VISIBLE lsp_array_base
0020 : public local_counted_base {
0021 public:
0022 void set(sp_counted_base* base) noexcept {
0023 count_ = shared_count(base);
0024 }
0025
0026 void local_cb_destroy() noexcept override {
0027 shared_count().swap(count_);
0028 }
0029
0030 shared_count local_cb_get_shared_count() const
0031 noexcept override {
0032 return count_;
0033 }
0034
0035 private:
0036 shared_count count_;
0037 };
0038
0039 template<class A>
0040 class lsp_array_state
0041 : public sp_array_state<A> {
0042 public:
0043 template<class U>
0044 lsp_array_state(const U& other, std::size_t size) noexcept
0045 : sp_array_state<A>(other, size) { }
0046
0047 lsp_array_base& base() noexcept {
0048 return base_;
0049 }
0050
0051 private:
0052 lsp_array_base base_;
0053 };
0054
0055 template<class A, std::size_t N>
0056 class lsp_size_array_state
0057 : public sp_size_array_state<A, N> {
0058 public:
0059 template<class U>
0060 lsp_size_array_state(const U& other, std::size_t size) noexcept
0061 : sp_size_array_state<A, N>(other, size) { }
0062
0063 lsp_array_base& base() noexcept {
0064 return base_;
0065 }
0066
0067 private:
0068 lsp_array_base base_;
0069 };
0070
0071 }
0072
0073 template<class T, class A>
0074 inline typename std::enable_if<detail::sp_is_unbounded_array<T>::value,
0075 local_shared_ptr<T> >::type
0076 allocate_local_shared(const A& allocator, std::size_t count)
0077 {
0078 typedef typename detail::sp_array_element<T>::type element;
0079 typedef typename allocator_rebind<A, element>::type other;
0080 typedef detail::lsp_array_state<other> state;
0081 typedef detail::sp_array_base<state> base;
0082 detail::sp_array_result<other, base> result(allocator, count);
0083 base* node = result.get();
0084 element* start = detail::sp_array_start<element>(node);
0085 ::new(static_cast<void*>(node)) base(allocator, start, count);
0086 detail::lsp_array_base& local = node->state().base();
0087 local.set(node);
0088 result.release();
0089 return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
0090 &local);
0091 }
0092
0093 template<class T, class A>
0094 inline typename std::enable_if<detail::sp_is_bounded_array<T>::value,
0095 local_shared_ptr<T> >::type
0096 allocate_local_shared(const A& allocator)
0097 {
0098 enum {
0099 count = std::extent<T>::value
0100 };
0101 typedef typename detail::sp_array_element<T>::type element;
0102 typedef typename allocator_rebind<A, element>::type other;
0103 typedef detail::lsp_size_array_state<other, count> state;
0104 typedef detail::sp_array_base<state> base;
0105 detail::sp_array_result<other, base> result(allocator, count);
0106 base* node = result.get();
0107 element* start = detail::sp_array_start<element>(node);
0108 ::new(static_cast<void*>(node)) base(allocator, start, count);
0109 detail::lsp_array_base& local = node->state().base();
0110 local.set(node);
0111 result.release();
0112 return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
0113 &local);
0114 }
0115
0116 template<class T, class A>
0117 inline typename std::enable_if<detail::sp_is_unbounded_array<T>::value,
0118 local_shared_ptr<T> >::type
0119 allocate_local_shared(const A& allocator, std::size_t count,
0120 const typename std::remove_extent<T>::type& value)
0121 {
0122 typedef typename detail::sp_array_element<T>::type element;
0123 typedef typename allocator_rebind<A, element>::type other;
0124 typedef detail::lsp_array_state<other> state;
0125 typedef detail::sp_array_base<state> base;
0126 detail::sp_array_result<other, base> result(allocator, count);
0127 base* node = result.get();
0128 element* start = detail::sp_array_start<element>(node);
0129 ::new(static_cast<void*>(node)) base(allocator, start, count, value);
0130 detail::lsp_array_base& local = node->state().base();
0131 local.set(node);
0132 result.release();
0133 return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
0134 &local);
0135 }
0136
0137 template<class T, class A>
0138 inline typename std::enable_if<detail::sp_is_bounded_array<T>::value,
0139 local_shared_ptr<T> >::type
0140 allocate_local_shared(const A& allocator,
0141 const typename std::remove_extent<T>::type& value)
0142 {
0143 enum {
0144 count = std::extent<T>::value
0145 };
0146 typedef typename detail::sp_array_element<T>::type element;
0147 typedef typename allocator_rebind<A, element>::type other;
0148 typedef detail::lsp_size_array_state<other, count> state;
0149 typedef detail::sp_array_base<state> base;
0150 detail::sp_array_result<other, base> result(allocator, count);
0151 base* node = result.get();
0152 element* start = detail::sp_array_start<element>(node);
0153 ::new(static_cast<void*>(node)) base(allocator, start, count, value);
0154 detail::lsp_array_base& local = node->state().base();
0155 local.set(node);
0156 result.release();
0157 return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
0158 &local);
0159 }
0160
0161 template<class T, class A>
0162 inline typename std::enable_if<detail::sp_is_unbounded_array<T>::value,
0163 local_shared_ptr<T> >::type
0164 allocate_local_shared_noinit(const A& allocator, std::size_t count)
0165 {
0166 return boost::allocate_local_shared<T>(boost::noinit_adapt(allocator),
0167 count);
0168 }
0169
0170 template<class T, class A>
0171 inline typename std::enable_if<detail::sp_is_bounded_array<T>::value,
0172 local_shared_ptr<T> >::type
0173 allocate_local_shared_noinit(const A& allocator)
0174 {
0175 return boost::allocate_local_shared<T>(boost::noinit_adapt(allocator));
0176 }
0177
0178 }
0179
0180 #endif