allocate_local_shared_array.hpp 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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. #include <boost/smart_ptr/detail/sp_type_traits.hpp>
  12. #include <type_traits>
  13. namespace boost {
  14. namespace detail {
  15. class BOOST_SYMBOL_VISIBLE lsp_array_base
  16. : public local_counted_base {
  17. public:
  18. void set(sp_counted_base* base) noexcept {
  19. count_ = shared_count(base);
  20. }
  21. void local_cb_destroy() noexcept override {
  22. shared_count().swap(count_);
  23. }
  24. shared_count local_cb_get_shared_count() const
  25. noexcept override {
  26. return count_;
  27. }
  28. private:
  29. shared_count count_;
  30. };
  31. template<class A>
  32. class lsp_array_state
  33. : public sp_array_state<A> {
  34. public:
  35. template<class U>
  36. lsp_array_state(const U& other, std::size_t size) noexcept
  37. : sp_array_state<A>(other, size) { }
  38. lsp_array_base& base() noexcept {
  39. return base_;
  40. }
  41. private:
  42. lsp_array_base base_;
  43. };
  44. template<class A, std::size_t N>
  45. class lsp_size_array_state
  46. : public sp_size_array_state<A, N> {
  47. public:
  48. template<class U>
  49. lsp_size_array_state(const U& other, std::size_t size) noexcept
  50. : sp_size_array_state<A, N>(other, size) { }
  51. lsp_array_base& base() noexcept {
  52. return base_;
  53. }
  54. private:
  55. lsp_array_base base_;
  56. };
  57. } /* detail */
  58. template<class T, class A>
  59. inline typename std::enable_if<detail::sp_is_unbounded_array<T>::value,
  60. local_shared_ptr<T> >::type
  61. allocate_local_shared(const A& allocator, std::size_t count)
  62. {
  63. typedef typename detail::sp_array_element<T>::type element;
  64. typedef typename allocator_rebind<A, element>::type other;
  65. typedef detail::lsp_array_state<other> state;
  66. typedef detail::sp_array_base<state> base;
  67. detail::sp_array_result<other, base> result(allocator, count);
  68. base* node = result.get();
  69. element* start = detail::sp_array_start<element>(node);
  70. ::new(static_cast<void*>(node)) base(allocator, start, count);
  71. detail::lsp_array_base& local = node->state().base();
  72. local.set(node);
  73. result.release();
  74. return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
  75. &local);
  76. }
  77. template<class T, class A>
  78. inline typename std::enable_if<detail::sp_is_bounded_array<T>::value,
  79. local_shared_ptr<T> >::type
  80. allocate_local_shared(const A& allocator)
  81. {
  82. enum {
  83. count = std::extent<T>::value
  84. };
  85. typedef typename detail::sp_array_element<T>::type element;
  86. typedef typename allocator_rebind<A, element>::type other;
  87. typedef detail::lsp_size_array_state<other, count> state;
  88. typedef detail::sp_array_base<state> base;
  89. detail::sp_array_result<other, base> result(allocator, count);
  90. base* node = result.get();
  91. element* start = detail::sp_array_start<element>(node);
  92. ::new(static_cast<void*>(node)) base(allocator, start, count);
  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(), start,
  97. &local);
  98. }
  99. template<class T, class A>
  100. inline typename std::enable_if<detail::sp_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 std::remove_extent<T>::type& value)
  104. {
  105. typedef typename detail::sp_array_element<T>::type element;
  106. typedef typename allocator_rebind<A, element>::type other;
  107. typedef detail::lsp_array_state<other> state;
  108. typedef detail::sp_array_base<state> base;
  109. detail::sp_array_result<other, base> result(allocator, count);
  110. base* node = result.get();
  111. element* start = detail::sp_array_start<element>(node);
  112. ::new(static_cast<void*>(node)) base(allocator, start, count, value);
  113. detail::lsp_array_base& local = node->state().base();
  114. local.set(node);
  115. result.release();
  116. return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
  117. &local);
  118. }
  119. template<class T, class A>
  120. inline typename std::enable_if<detail::sp_is_bounded_array<T>::value,
  121. local_shared_ptr<T> >::type
  122. allocate_local_shared(const A& allocator,
  123. const typename std::remove_extent<T>::type& value)
  124. {
  125. enum {
  126. count = std::extent<T>::value
  127. };
  128. typedef typename detail::sp_array_element<T>::type element;
  129. typedef typename allocator_rebind<A, element>::type other;
  130. typedef detail::lsp_size_array_state<other, count> state;
  131. typedef detail::sp_array_base<state> base;
  132. detail::sp_array_result<other, base> result(allocator, count);
  133. base* node = result.get();
  134. element* start = detail::sp_array_start<element>(node);
  135. ::new(static_cast<void*>(node)) base(allocator, start, count, value);
  136. detail::lsp_array_base& local = node->state().base();
  137. local.set(node);
  138. result.release();
  139. return local_shared_ptr<T>(detail::lsp_internal_constructor_tag(), start,
  140. &local);
  141. }
  142. template<class T, class A>
  143. inline typename std::enable_if<detail::sp_is_unbounded_array<T>::value,
  144. local_shared_ptr<T> >::type
  145. allocate_local_shared_noinit(const A& allocator, std::size_t count)
  146. {
  147. return boost::allocate_local_shared<T>(boost::noinit_adapt(allocator),
  148. count);
  149. }
  150. template<class T, class A>
  151. inline typename std::enable_if<detail::sp_is_bounded_array<T>::value,
  152. local_shared_ptr<T> >::type
  153. allocate_local_shared_noinit(const A& allocator)
  154. {
  155. return boost::allocate_local_shared<T>(boost::noinit_adapt(allocator));
  156. }
  157. } /* boost */
  158. #endif