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