allocate_local_shared_array.hpp 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. /*
  2. Copyright 2017-2019 Glen Joseph Fernandes
  3. (glenjofe@gmail.com)
  4. Distributed under the Boost Software License, Version 1.0.
  5. (http://www.boost.org/LICENSE_1_0.txt)
  6. */
  7. #ifndef BOOST_SMART_PTR_ALLOCATE_LOCAL_SHARED_ARRAY_HPP
  8. #define BOOST_SMART_PTR_ALLOCATE_LOCAL_SHARED_ARRAY_HPP
  9. #include <boost/smart_ptr/allocate_shared_array.hpp>
  10. #include <boost/smart_ptr/local_shared_ptr.hpp>
  11. namespace boost {
  12. namespace detail {
  13. class BOOST_SYMBOL_VISIBLE lsp_array_base
  14. : public local_counted_base {
  15. public:
  16. void set(sp_counted_base* base) BOOST_SP_NOEXCEPT {
  17. count_ = shared_count(base);
  18. }
  19. virtual void local_cb_destroy() BOOST_SP_NOEXCEPT {
  20. shared_count().swap(count_);
  21. }
  22. virtual shared_count local_cb_get_shared_count() const BOOST_SP_NOEXCEPT {
  23. return count_;
  24. }
  25. private:
  26. shared_count count_;
  27. };
  28. template<class A>
  29. class lsp_array_state
  30. : public sp_array_state<A> {
  31. public:
  32. template<class U>
  33. lsp_array_state(const U& other, std::size_t size) BOOST_SP_NOEXCEPT
  34. : sp_array_state<A>(other, size) { }
  35. lsp_array_base& base() BOOST_SP_NOEXCEPT {
  36. return base_;
  37. }
  38. private:
  39. lsp_array_base base_;
  40. };
  41. template<class A, std::size_t N>
  42. class lsp_size_array_state
  43. : public sp_size_array_state<A, N> {
  44. public:
  45. template<class U>
  46. lsp_size_array_state(const U& other, std::size_t size) BOOST_SP_NOEXCEPT
  47. : sp_size_array_state<A, N>(other, size) { }
  48. lsp_array_base& base() BOOST_SP_NOEXCEPT {
  49. return base_;
  50. }
  51. private:
  52. lsp_array_base base_;
  53. };
  54. } /* detail */
  55. template<class T, class A>
  56. inline typename enable_if_<is_unbounded_array<T>::value,
  57. local_shared_ptr<T> >::type
  58. allocate_local_shared(const A& allocator, std::size_t count)
  59. {
  60. typedef typename remove_extent<T>::type type;
  61. typedef typename detail::sp_array_scalar<T>::type scalar;
  62. typedef typename detail::sp_bind_allocator<A, scalar>::type other;
  63. typedef detail::lsp_array_state<other> state;
  64. typedef detail::sp_array_base<state> base;
  65. std::size_t size = count * detail::sp_array_count<type, scalar>::value;
  66. detail::sp_array_result<other, base> result(allocator, size);
  67. base* node = result.get();
  68. scalar* start = detail::sp_array_start<base, scalar>(node);
  69. ::new(static_cast<void*>(node)) base(allocator, size, start);
  70. detail::lsp_array_base& local = node->state().base();
  71. local.set(node);
  72. result.release();
  73. return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
  74. reinterpret_cast<type*>(start), &local);
  75. }
  76. template<class T, class A>
  77. inline typename enable_if_<is_bounded_array<T>::value,
  78. local_shared_ptr<T> >::type
  79. allocate_local_shared(const A& allocator)
  80. {
  81. typedef typename remove_extent<T>::type type;
  82. typedef typename detail::sp_array_scalar<T>::type scalar;
  83. typedef typename detail::sp_bind_allocator<A, scalar>::type other;
  84. enum {
  85. size = detail::sp_array_count<T, scalar>::value
  86. };
  87. typedef detail::lsp_size_array_state<other, size> state;
  88. typedef detail::sp_array_base<state> base;
  89. detail::sp_array_result<other, base> result(allocator, size);
  90. base* node = result.get();
  91. scalar* start = detail::sp_array_start<base, scalar>(node);
  92. ::new(static_cast<void*>(node)) base(allocator, size, start);
  93. detail::lsp_array_base& local = node->state().base();
  94. local.set(node);
  95. result.release();
  96. return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
  97. reinterpret_cast<type*>(start), &local);
  98. }
  99. template<class T, class A>
  100. inline typename enable_if_<is_unbounded_array<T>::value,
  101. local_shared_ptr<T> >::type
  102. allocate_local_shared(const A& allocator, std::size_t count,
  103. const typename remove_extent<T>::type& value)
  104. {
  105. typedef typename remove_extent<T>::type type;
  106. typedef typename detail::sp_array_scalar<T>::type scalar;
  107. typedef typename detail::sp_bind_allocator<A, scalar>::type other;
  108. typedef detail::lsp_array_state<other> state;
  109. typedef detail::sp_array_base<state> base;
  110. enum {
  111. total = detail::sp_array_count<type, scalar>::value
  112. };
  113. std::size_t size = count * total;
  114. detail::sp_array_result<other, base> result(allocator, size);
  115. base* node = result.get();
  116. scalar* start = detail::sp_array_start<base, scalar>(node);
  117. ::new(static_cast<void*>(node)) base(allocator, size,
  118. reinterpret_cast<const scalar*>(&value), total, start);
  119. detail::lsp_array_base& local = node->state().base();
  120. local.set(node);
  121. result.release();
  122. return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
  123. reinterpret_cast<type*>(start), &local);
  124. }
  125. template<class T, class A>
  126. inline typename enable_if_<is_bounded_array<T>::value,
  127. local_shared_ptr<T> >::type
  128. allocate_local_shared(const A& allocator,
  129. const typename remove_extent<T>::type& value)
  130. {
  131. typedef typename remove_extent<T>::type type;
  132. typedef typename detail::sp_array_scalar<T>::type scalar;
  133. typedef typename detail::sp_bind_allocator<A, scalar>::type other;
  134. enum {
  135. size = detail::sp_array_count<T, scalar>::value
  136. };
  137. typedef detail::lsp_size_array_state<other, size> state;
  138. typedef detail::sp_array_base<state> base;
  139. detail::sp_array_result<other, base> result(allocator, size);
  140. base* node = result.get();
  141. scalar* start = detail::sp_array_start<base, scalar>(node);
  142. ::new(static_cast<void*>(node)) base(allocator, size,
  143. reinterpret_cast<const scalar*>(&value),
  144. detail::sp_array_count<type, scalar>::value, start);
  145. detail::lsp_array_base& local = node->state().base();
  146. local.set(node);
  147. result.release();
  148. return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
  149. reinterpret_cast<type*>(start), &local);
  150. }
  151. template<class T, class A>
  152. inline typename enable_if_<is_unbounded_array<T>::value,
  153. local_shared_ptr<T> >::type
  154. allocate_local_shared_noinit(const A& allocator, std::size_t count)
  155. {
  156. typedef typename remove_extent<T>::type type;
  157. typedef typename detail::sp_array_scalar<T>::type scalar;
  158. typedef typename detail::sp_bind_allocator<A, scalar>::type other;
  159. typedef detail::lsp_array_state<other> state;
  160. typedef detail::sp_array_base<state, false> base;
  161. std::size_t size = count * detail::sp_array_count<type, scalar>::value;
  162. detail::sp_array_result<other, base> result(allocator, size);
  163. base* node = result.get();
  164. scalar* start = detail::sp_array_start<base, scalar>(node);
  165. ::new(static_cast<void*>(node)) base(detail::sp_default(), allocator,
  166. size, start);
  167. detail::lsp_array_base& local = node->state().base();
  168. local.set(node);
  169. result.release();
  170. return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
  171. reinterpret_cast<type*>(start), &local);
  172. }
  173. template<class T, class A>
  174. inline typename enable_if_<is_bounded_array<T>::value,
  175. local_shared_ptr<T> >::type
  176. allocate_local_shared_noinit(const A& allocator)
  177. {
  178. typedef typename remove_extent<T>::type type;
  179. typedef typename detail::sp_array_scalar<T>::type scalar;
  180. typedef typename detail::sp_bind_allocator<A, scalar>::type other;
  181. enum {
  182. size = detail::sp_array_count<T, scalar>::value
  183. };
  184. typedef detail::lsp_size_array_state<other, size> state;
  185. typedef detail::sp_array_base<state, false> base;
  186. detail::sp_array_result<other, base> result(allocator, size);
  187. base* node = result.get();
  188. scalar* start = detail::sp_array_start<base, scalar>(node);
  189. ::new(static_cast<void*>(node)) base(detail::sp_default(), allocator,
  190. size, start);
  191. detail::lsp_array_base& local = node->state().base();
  192. local.set(node);
  193. result.release();
  194. return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
  195. reinterpret_cast<type*>(start), &local);
  196. }
  197. } /* boost */
  198. #endif