1 /*
2  * Copyright (c) 2012-2014 Glen Joseph Fernandes
3  * glenfe at live dot com
4  *
5  * Distributed under the Boost Software License,
6  * Version 1.0. (See accompanying file LICENSE_1_0.txt
7  * or copy at http://boost.org/LICENSE_1_0.txt)
8  */
9 #ifndef BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP
10 #define BOOST_SMART_PTR_ALLOCATE_SHARED_ARRAY_HPP
11 
12 #include <boost/smart_ptr/detail/array_count_impl.hpp>
13 #include <boost/smart_ptr/detail/sp_if_array.hpp>
14 
15 namespace boost {
16     template<class T, class A>
17     inline typename boost::detail::sp_if_array<T>::type
allocate_shared(const A & allocator,std::size_t size)18     allocate_shared(const A& allocator, std::size_t size) {
19         typedef typename boost::detail::array_inner<T>::type T1;
20         typedef typename boost::detail::array_base<T1>::type T2;
21         typedef boost::detail::ms_init_tag R1;
22         typedef boost::detail::as_allocator<A, T, R1> A1;
23         typedef boost::detail::ms_in_allocator_tag D1;
24         std::size_t n1 = size * boost::detail::array_total<T1>::size;
25         T1* p1 = 0;
26         T2* p2 = 0;
27         D1 d1;
28         A1 a1(allocator, size, &p2);
29         shared_ptr<T> s1(p1, d1, a1);
30         A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
31         a2->set(0);
32 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
33         boost::detail::as_init(allocator, p2, n1);
34 #else
35         boost::detail::ms_init(p2, n1);
36 #endif
37         a2->set(p2);
38         p1 = reinterpret_cast<T1*>(p2);
39         return shared_ptr<T>(s1, p1);
40     }
41 
42     template<class T, class A>
43     inline typename boost::detail::sp_if_size_array<T>::type
allocate_shared(const A & allocator)44     allocate_shared(const A& allocator) {
45         typedef typename boost::detail::array_inner<T>::type T1;
46         typedef typename boost::detail::array_base<T1>::type T2;
47         typedef boost::detail::ms_init_tag R1;
48         typedef boost::detail::as_allocator<A, T, R1> A1;
49         typedef boost::detail::ms_in_allocator_tag D1;
50         enum {
51             N = boost::detail::array_total<T>::size
52         };
53         T1* p1 = 0;
54         T2* p2 = 0;
55         D1 d1;
56         A1 a1(allocator, &p2);
57         shared_ptr<T> s1(p1, d1, a1);
58         A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
59         a2->set(0);
60 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
61         boost::detail::as_init(allocator, p2, N);
62 #else
63         boost::detail::ms_init(p2, N);
64 #endif
65         a2->set(p2);
66         p1 = reinterpret_cast<T1*>(p2);
67         return shared_ptr<T>(s1, p1);
68     }
69 
70     template<class T, class A>
71     inline typename boost::detail::sp_if_array<T>::type
allocate_shared(const A & allocator,std::size_t size,const typename boost::detail::array_inner<T>::type & value)72     allocate_shared(const A& allocator, std::size_t size,
73         const typename boost::detail::array_inner<T>::type& value) {
74         typedef typename boost::detail::array_inner<T>::type T1;
75         typedef typename boost::detail::array_base<T1>::type T2;
76         typedef const T2 T3;
77         typedef boost::detail::ms_init_tag R1;
78         typedef boost::detail::as_allocator<A, T, R1> A1;
79         typedef boost::detail::ms_in_allocator_tag D1;
80         enum {
81             M = boost::detail::array_total<T1>::size
82         };
83         std::size_t n1 = M * size;
84         T1* p1 = 0;
85         T2* p2 = 0;
86         T3* p3 = reinterpret_cast<T3*>(&value);
87         D1 d1;
88         A1 a1(allocator, size, &p2);
89         shared_ptr<T> s1(p1, d1, a1);
90         A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
91         a2->set(0);
92 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
93         boost::detail::as_init<T2, A, M>(allocator, p2, n1, p3);
94 #else
95         boost::detail::ms_init<T2, M>(p2, n1, p3);
96 #endif
97         a2->set(p2);
98         p1 = reinterpret_cast<T1*>(p2);
99         return shared_ptr<T>(s1, p1);
100     }
101 
102     template<class T, class A>
103     inline typename boost::detail::sp_if_size_array<T>::type
allocate_shared(const A & allocator,const typename boost::detail::array_inner<T>::type & value)104     allocate_shared(const A& allocator,
105         const typename boost::detail::array_inner<T>::type& value) {
106         typedef typename boost::detail::array_inner<T>::type T1;
107         typedef typename boost::detail::array_base<T1>::type T2;
108         typedef const T2 T3;
109         typedef boost::detail::ms_init_tag R1;
110         typedef boost::detail::as_allocator<A, T, R1> A1;
111         typedef boost::detail::ms_in_allocator_tag D1;
112         enum {
113             N = boost::detail::array_total<T>::size,
114             M = boost::detail::array_total<T1>::size
115         };
116         T1* p1 = 0;
117         T2* p2 = 0;
118         T3* p3 = reinterpret_cast<T3*>(&value);
119         D1 d1;
120         A1 a1(allocator, &p2);
121         shared_ptr<T> s1(p1, d1, a1);
122         A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
123         a2->set(0);
124 #if !defined(BOOST_NO_CXX11_ALLOCATOR)
125         boost::detail::as_init<T2, A, M>(allocator, p2, N, p3);
126 #else
127         boost::detail::ms_init<T2,  M>(p2, N, p3);
128 #endif
129         a2->set(p2);
130         p1 = reinterpret_cast<T1*>(p2);
131         return shared_ptr<T>(s1, p1);
132     }
133 
134     template<class T, class A>
135     inline typename boost::detail::sp_if_array<T>::type
allocate_shared_noinit(const A & allocator,std::size_t size)136     allocate_shared_noinit(const A& allocator, std::size_t size) {
137         typedef typename boost::detail::array_inner<T>::type T1;
138         typedef typename boost::detail::array_base<T1>::type T2;
139         typedef boost::detail::ms_noinit_tag R1;
140         typedef boost::detail::as_allocator<A, T, R1> A1;
141         typedef boost::detail::ms_in_allocator_tag D1;
142         std::size_t n1 = size * boost::detail::array_total<T1>::size;
143         T1* p1 = 0;
144         T2* p2 = 0;
145         D1 d1;
146         A1 a1(allocator, size, &p2);
147         shared_ptr<T> s1(p1, d1, a1);
148         A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
149         a2->set(0);
150         boost::detail::ms_noinit(p2, n1);
151         a2->set(p2);
152         p1 = reinterpret_cast<T1*>(p2);
153         return shared_ptr<T>(s1, p1);
154     }
155 
156     template<class T, class A>
157     inline typename boost::detail::sp_if_size_array<T>::type
allocate_shared_noinit(const A & allocator)158     allocate_shared_noinit(const A& allocator) {
159         typedef typename boost::detail::array_inner<T>::type T1;
160         typedef typename boost::detail::array_base<T1>::type T2;
161         typedef boost::detail::ms_noinit_tag R1;
162         typedef boost::detail::as_allocator<A, T, R1> A1;
163         typedef boost::detail::ms_in_allocator_tag D1;
164         enum {
165             N = boost::detail::array_total<T>::size
166         };
167         T1* p1 = 0;
168         T2* p2 = 0;
169         D1 d1;
170         A1 a1(allocator, &p2);
171         shared_ptr<T> s1(p1, d1, a1);
172         A1* a2 = static_cast<A1*>(s1._internal_get_untyped_deleter());
173         a2->set(0);
174         boost::detail::ms_noinit(p2, N);
175         a2->set(p2);
176         p1 = reinterpret_cast<T1*>(p2);
177         return shared_ptr<T>(s1, p1);
178     }
179 }
180 
181 #endif
182