allocate_local_shared_array.hpp 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. /*
  2. Copyright 2017 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. template<class>
  14. struct lsp_if_array { };
  15. template<class T>
  16. struct lsp_if_array<T[]> {
  17. typedef boost::local_shared_ptr<T[]> type;
  18. };
  19. template<class>
  20. struct lsp_if_size_array { };
  21. template<class T, std::size_t N>
  22. struct lsp_if_size_array<T[N]> {
  23. typedef boost::local_shared_ptr<T[N]> type;
  24. };
  25. class lsp_array_base
  26. : public local_counted_base {
  27. public:
  28. void set(sp_counted_base* base) BOOST_SP_NOEXCEPT {
  29. count_ = shared_count(base);
  30. }
  31. virtual void local_cb_destroy() BOOST_SP_NOEXCEPT {
  32. shared_count().swap(count_);
  33. }
  34. virtual shared_count local_cb_get_shared_count() const BOOST_SP_NOEXCEPT {
  35. return count_;
  36. }
  37. private:
  38. shared_count count_;
  39. };
  40. template<class A>
  41. class lsp_array_state
  42. : public sp_array_state<A> {
  43. public:
  44. template<class U>
  45. lsp_array_state(const U& other, std::size_t size) BOOST_SP_NOEXCEPT
  46. : sp_array_state<A>(other, size) { }
  47. lsp_array_base& base() BOOST_SP_NOEXCEPT {
  48. return base_;
  49. }
  50. private:
  51. lsp_array_base base_;
  52. };
  53. template<class A, std::size_t N>
  54. class lsp_size_array_state
  55. : public sp_size_array_state<A, N> {
  56. public:
  57. template<class U>
  58. lsp_size_array_state(const U& other, std::size_t size) BOOST_SP_NOEXCEPT
  59. : sp_size_array_state<A, N>(other, size) { }
  60. lsp_array_base& base() BOOST_SP_NOEXCEPT {
  61. return base_;
  62. }
  63. private:
  64. lsp_array_base base_;
  65. };
  66. } /* detail */
  67. template<class T, class A>
  68. inline typename detail::lsp_if_array<T>::type
  69. allocate_local_shared(const A& allocator, std::size_t count)
  70. {
  71. typedef typename detail::sp_array_element<T>::type type;
  72. typedef typename detail::sp_array_scalar<T>::type scalar;
  73. typedef typename detail::sp_bind_allocator<A, scalar>::type other;
  74. typedef detail::lsp_array_state<other> state;
  75. typedef detail::sp_array_base<state> base;
  76. std::size_t size = count * detail::sp_array_count<type>::value;
  77. detail::sp_array_result<other, base> result(allocator, size);
  78. base* node = result.get();
  79. scalar* start = detail::sp_array_start<base, scalar>(node);
  80. ::new(static_cast<void*>(node)) base(allocator, size, start);
  81. detail::lsp_array_base& local = node->state().base();
  82. local.set(node);
  83. result.release();
  84. return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
  85. reinterpret_cast<type*>(start), &local);
  86. }
  87. template<class T, class A>
  88. inline typename detail::lsp_if_size_array<T>::type
  89. allocate_local_shared(const A& allocator)
  90. {
  91. enum {
  92. size = detail::sp_array_count<T>::value
  93. };
  94. typedef typename detail::sp_array_element<T>::type type;
  95. typedef typename detail::sp_array_scalar<T>::type scalar;
  96. typedef typename detail::sp_bind_allocator<A, scalar>::type other;
  97. typedef detail::lsp_size_array_state<other, size> state;
  98. typedef detail::sp_array_base<state> base;
  99. detail::sp_array_result<other, base> result(allocator, size);
  100. base* node = result.get();
  101. scalar* start = detail::sp_array_start<base, scalar>(node);
  102. ::new(static_cast<void*>(node)) base(allocator, size, start);
  103. detail::lsp_array_base& local = node->state().base();
  104. local.set(node);
  105. result.release();
  106. return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
  107. reinterpret_cast<type*>(start), &local);
  108. }
  109. template<class T, class A>
  110. inline typename detail::lsp_if_array<T>::type
  111. allocate_local_shared(const A& allocator, std::size_t count,
  112. const typename detail::sp_array_element<T>::type& value)
  113. {
  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_array_state<other> state;
  118. typedef detail::sp_array_base<state> base;
  119. std::size_t size = count * detail::sp_array_count<type>::value;
  120. detail::sp_array_result<other, base> result(allocator, size);
  121. base* node = result.get();
  122. scalar* start = detail::sp_array_start<base, scalar>(node);
  123. ::new(static_cast<void*>(node)) base(allocator, size,
  124. reinterpret_cast<const scalar*>(&value),
  125. detail::sp_array_count<type>::value, start);
  126. detail::lsp_array_base& local = node->state().base();
  127. local.set(node);
  128. result.release();
  129. return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
  130. reinterpret_cast<type*>(start), &local);
  131. }
  132. template<class T, class A>
  133. inline typename detail::lsp_if_size_array<T>::type
  134. allocate_local_shared(const A& allocator,
  135. const typename detail::sp_array_element<T>::type& value)
  136. {
  137. enum {
  138. size = detail::sp_array_count<T>::value
  139. };
  140. typedef typename detail::sp_array_element<T>::type type;
  141. typedef typename detail::sp_array_scalar<T>::type scalar;
  142. typedef typename detail::sp_bind_allocator<A, scalar>::type other;
  143. typedef detail::lsp_size_array_state<other, size> state;
  144. typedef detail::sp_array_base<state> base;
  145. detail::sp_array_result<other, base> result(allocator, size);
  146. base* node = result.get();
  147. scalar* start = detail::sp_array_start<base, scalar>(node);
  148. ::new(static_cast<void*>(node)) base(allocator, size,
  149. reinterpret_cast<const scalar*>(&value),
  150. detail::sp_array_count<type>::value, start);
  151. detail::lsp_array_base& local = node->state().base();
  152. local.set(node);
  153. result.release();
  154. return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
  155. reinterpret_cast<type*>(start), &local);
  156. }
  157. template<class T, class A>
  158. inline typename detail::lsp_if_array<T>::type
  159. allocate_local_shared_noinit(const A& allocator, std::size_t count)
  160. {
  161. typedef typename detail::sp_array_element<T>::type type;
  162. typedef typename detail::sp_array_scalar<T>::type scalar;
  163. typedef typename detail::sp_bind_allocator<A, scalar>::type other;
  164. typedef detail::lsp_array_state<other> state;
  165. typedef detail::sp_array_base<state, false> base;
  166. std::size_t size = count * detail::sp_array_count<type>::value;
  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(detail::sp_default(), allocator,
  171. size, start);
  172. detail::lsp_array_base& local = node->state().base();
  173. local.set(node);
  174. result.release();
  175. return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
  176. reinterpret_cast<type*>(start), &local);
  177. }
  178. template<class T, class A>
  179. inline typename detail::lsp_if_size_array<T>::type
  180. allocate_local_shared_noinit(const A& allocator)
  181. {
  182. enum {
  183. size = detail::sp_array_count<T>::value
  184. };
  185. typedef typename detail::sp_array_element<T>::type type;
  186. typedef typename detail::sp_array_scalar<T>::type scalar;
  187. typedef typename detail::sp_bind_allocator<A, scalar>::type other;
  188. typedef detail::lsp_size_array_state<other, size> state;
  189. typedef detail::sp_array_base<state, false> base;
  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,
  194. size, start);
  195. detail::lsp_array_base& local = node->state().base();
  196. local.set(node);
  197. result.release();
  198. return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(),
  199. reinterpret_cast<type*>(start), &local);
  200. }
  201. } /* boost */
  202. #endif