2 Copyright 2017 Glen Joseph Fernandes
5 Distributed under the Boost Software License, Version 1.0.
6 (http://www.boost.org/LICENSE_1_0.txt)
8 #ifndef BOOST_SMART_PTR_ALLOCATE_LOCAL_SHARED_ARRAY_HPP
9 #define BOOST_SMART_PTR_ALLOCATE_LOCAL_SHARED_ARRAY_HPP
11 #include <boost/smart_ptr/allocate_shared_array.hpp>
12 #include <boost/smart_ptr/local_shared_ptr.hpp>
18 struct lsp_if_array { };
21 struct lsp_if_array<T[]> {
22 typedef boost::local_shared_ptr<T[]> type;
26 struct lsp_if_size_array { };
28 template<class T, std::size_t N>
29 struct lsp_if_size_array<T[N]> {
30 typedef boost::local_shared_ptr<T[N]> type;
34 : public local_counted_base {
36 void set(sp_counted_base* base) BOOST_SP_NOEXCEPT {
37 count_ = shared_count(base);
40 virtual void local_cb_destroy() BOOST_SP_NOEXCEPT {
41 shared_count().swap(count_);
44 virtual shared_count local_cb_get_shared_count() const BOOST_SP_NOEXCEPT {
54 : public sp_array_state<A> {
57 lsp_array_state(const U& other, std::size_t size) BOOST_SP_NOEXCEPT
58 : sp_array_state<A>(other, size) { }
60 lsp_array_base& base() BOOST_SP_NOEXCEPT {
68 template<class A, std::size_t N>
69 class lsp_size_array_state
70 : public sp_size_array_state<A, N> {
73 lsp_size_array_state(const U& other, std::size_t size) BOOST_SP_NOEXCEPT
74 : sp_size_array_state<A, N>(other, size) { }
76 lsp_array_base& base() BOOST_SP_NOEXCEPT {
86 template<class T, class A>
87 inline typename detail::lsp_if_array<T>::type
88 allocate_local_shared(const A& allocator, std::size_t count)
90 typedef typename detail::sp_array_element<T>::type type;
91 typedef typename detail::sp_array_scalar<T>::type scalar;
92 typedef typename detail::sp_bind_allocator<A, scalar>::type other;
93 typedef detail::lsp_array_state<other> state;
94 typedef detail::sp_array_base<state> base;
95 std::size_t size = count * detail::sp_array_count<type>::value;
96 detail::sp_array_result<other, base> result(allocator, size);
97 base* node = result.get();
98 scalar* start = detail::sp_array_start<base, scalar>(node);
99 ::new(static_cast<void*>(node)) base(allocator, size, start);
100 detail::lsp_array_base& local = node->state().base();
103 return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
104 reinterpret_cast<type*>(start), &local);
107 template<class T, class A>
108 inline typename detail::lsp_if_size_array<T>::type
109 allocate_local_shared(const A& allocator)
112 size = detail::sp_array_count<T>::value
114 typedef typename detail::sp_array_element<T>::type type;
115 typedef typename detail::sp_array_scalar<T>::type scalar;
116 typedef typename detail::sp_bind_allocator<A, scalar>::type other;
117 typedef detail::lsp_size_array_state<other, size> state;
118 typedef detail::sp_array_base<state> base;
119 detail::sp_array_result<other, base> result(allocator, size);
120 base* node = result.get();
121 scalar* start = detail::sp_array_start<base, scalar>(node);
122 ::new(static_cast<void*>(node)) base(allocator, size, start);
123 detail::lsp_array_base& local = node->state().base();
126 return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
127 reinterpret_cast<type*>(start), &local);
130 template<class T, class A>
131 inline typename detail::lsp_if_array<T>::type
132 allocate_local_shared(const A& allocator, std::size_t count,
133 const typename detail::sp_array_element<T>::type& value)
135 typedef typename detail::sp_array_element<T>::type type;
136 typedef typename detail::sp_array_scalar<T>::type scalar;
137 typedef typename detail::sp_bind_allocator<A, scalar>::type other;
138 typedef detail::lsp_array_state<other> state;
139 typedef detail::sp_array_base<state> base;
140 std::size_t size = count * detail::sp_array_count<type>::value;
141 detail::sp_array_result<other, base> result(allocator, size);
142 base* node = result.get();
143 scalar* start = detail::sp_array_start<base, scalar>(node);
144 ::new(static_cast<void*>(node)) base(allocator, size,
145 reinterpret_cast<const scalar*>(&value),
146 detail::sp_array_count<type>::value, start);
147 detail::lsp_array_base& local = node->state().base();
150 return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
151 reinterpret_cast<type*>(start), &local);
154 template<class T, class A>
155 inline typename detail::lsp_if_size_array<T>::type
156 allocate_local_shared(const A& allocator,
157 const typename detail::sp_array_element<T>::type& value)
160 size = detail::sp_array_count<T>::value
162 typedef typename detail::sp_array_element<T>::type type;
163 typedef typename detail::sp_array_scalar<T>::type scalar;
164 typedef typename detail::sp_bind_allocator<A, scalar>::type other;
165 typedef detail::lsp_size_array_state<other, size> state;
166 typedef detail::sp_array_base<state> base;
167 detail::sp_array_result<other, base> result(allocator, size);
168 base* node = result.get();
169 scalar* start = detail::sp_array_start<base, scalar>(node);
170 ::new(static_cast<void*>(node)) base(allocator, size,
171 reinterpret_cast<const scalar*>(&value),
172 detail::sp_array_count<type>::value, start);
173 detail::lsp_array_base& local = node->state().base();
176 return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
177 reinterpret_cast<type*>(start), &local);
180 template<class T, class A>
181 inline typename detail::lsp_if_array<T>::type
182 allocate_local_shared_noinit(const A& allocator, std::size_t count)
184 typedef typename detail::sp_array_element<T>::type type;
185 typedef typename detail::sp_array_scalar<T>::type scalar;
186 typedef typename detail::sp_bind_allocator<A, scalar>::type other;
187 typedef detail::lsp_array_state<other> state;
188 typedef detail::sp_array_base<state, false> base;
189 std::size_t size = count * detail::sp_array_count<type>::value;
190 detail::sp_array_result<other, base> result(allocator, size);
191 base* node = result.get();
192 scalar* start = detail::sp_array_start<base, scalar>(node);
193 ::new(static_cast<void*>(node)) base(detail::sp_default(), allocator,
195 detail::lsp_array_base& local = node->state().base();
198 return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
199 reinterpret_cast<type*>(start), &local);
202 template<class T, class A>
203 inline typename detail::lsp_if_size_array<T>::type
204 allocate_local_shared_noinit(const A& allocator)
207 size = detail::sp_array_count<T>::value
209 typedef typename detail::sp_array_element<T>::type type;
210 typedef typename detail::sp_array_scalar<T>::type scalar;
211 typedef typename detail::sp_bind_allocator<A, scalar>::type other;
212 typedef detail::lsp_size_array_state<other, size> state;
213 typedef detail::sp_array_base<state, false> base;
214 detail::sp_array_result<other, base> result(allocator, size);
215 base* node = result.get();
216 scalar* start = detail::sp_array_start<base, scalar>(node);
217 ::new(static_cast<void*>(node)) base(detail::sp_default(), allocator,
219 detail::lsp_array_base& local = node->state().base();
222 return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
223 reinterpret_cast<type*>(start), &local);