allocate_local_shared_array.hpp 5.6 KB

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