allocate_local_shared_array.hpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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 detail::sp_array_element<T>::type element;
  61. typedef typename detail::sp_bind_allocator<A, element>::type other;
  62. typedef detail::lsp_array_state<other> state;
  63. typedef detail::sp_array_base<state> base;
  64. detail::sp_array_result<other, base> result(allocator, count);
  65. base* node = result.get();
  66. element* start = detail::sp_array_start<element>(node);
  67. ::new(static_cast<void*>(node)) base(allocator, start, count);
  68. detail::lsp_array_base& local = node->state().base();
  69. local.set(node);
  70. result.release();
  71. return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
  72. &local);
  73. }
  74. template<class T, class A>
  75. inline typename enable_if_<is_bounded_array<T>::value,
  76. local_shared_ptr<T> >::type
  77. allocate_local_shared(const A& allocator)
  78. {
  79. enum {
  80. count = extent<T>::value
  81. };
  82. typedef typename detail::sp_array_element<T>::type element;
  83. typedef typename detail::sp_bind_allocator<A, element>::type other;
  84. typedef detail::lsp_size_array_state<other, count> state;
  85. typedef detail::sp_array_base<state> base;
  86. detail::sp_array_result<other, base> result(allocator, count);
  87. base* node = result.get();
  88. element* start = detail::sp_array_start<element>(node);
  89. ::new(static_cast<void*>(node)) base(allocator, start, count);
  90. detail::lsp_array_base& local = node->state().base();
  91. local.set(node);
  92. result.release();
  93. return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
  94. &local);
  95. }
  96. template<class T, class A>
  97. inline typename enable_if_<is_unbounded_array<T>::value,
  98. local_shared_ptr<T> >::type
  99. allocate_local_shared(const A& allocator, std::size_t count,
  100. const typename remove_extent<T>::type& value)
  101. {
  102. typedef typename detail::sp_array_element<T>::type element;
  103. typedef typename detail::sp_bind_allocator<A, element>::type other;
  104. typedef detail::lsp_array_state<other> state;
  105. typedef detail::sp_array_base<state> base;
  106. detail::sp_array_result<other, base> result(allocator, count);
  107. base* node = result.get();
  108. element* start = detail::sp_array_start<element>(node);
  109. ::new(static_cast<void*>(node)) base(allocator, start, count, value);
  110. detail::lsp_array_base& local = node->state().base();
  111. local.set(node);
  112. result.release();
  113. return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
  114. &local);
  115. }
  116. template<class T, class A>
  117. inline typename enable_if_<is_bounded_array<T>::value,
  118. local_shared_ptr<T> >::type
  119. allocate_local_shared(const A& allocator,
  120. const typename remove_extent<T>::type& value)
  121. {
  122. enum {
  123. count = extent<T>::value
  124. };
  125. typedef typename detail::sp_array_element<T>::type element;
  126. typedef typename detail::sp_bind_allocator<A, element>::type other;
  127. typedef detail::lsp_size_array_state<other, count> state;
  128. typedef detail::sp_array_base<state> base;
  129. detail::sp_array_result<other, base> result(allocator, count);
  130. base* node = result.get();
  131. element* start = detail::sp_array_start<element>(node);
  132. ::new(static_cast<void*>(node)) base(allocator, start, count, value);
  133. detail::lsp_array_base& local = node->state().base();
  134. local.set(node);
  135. result.release();
  136. return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
  137. &local);
  138. }
  139. template<class T, class A>
  140. inline typename enable_if_<is_unbounded_array<T>::value,
  141. local_shared_ptr<T> >::type
  142. allocate_local_shared_noinit(const A& allocator, std::size_t count)
  143. {
  144. return boost::allocate_local_shared<T>(boost::noinit_adapt(allocator),
  145. count);
  146. }
  147. template<class T, class A>
  148. inline typename enable_if_<is_bounded_array<T>::value,
  149. local_shared_ptr<T> >::type
  150. allocate_local_shared_noinit(const A& allocator)
  151. {
  152. return boost::allocate_local_shared<T>(boost::noinit_adapt(allocator));
  153. }
  154. } /* boost */
  155. #endif