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_DETAIL_ARRAY_UTILITY_HPP |
10 | #define BOOST_SMART_PTR_DETAIL_ARRAY_UTILITY_HPP |
11 | |
12 | #include <boost/config.hpp> |
13 | #include <boost/type_traits/has_trivial_constructor.hpp> |
14 | #include <boost/type_traits/has_trivial_destructor.hpp> |
15 | #if !defined(BOOST_NO_CXX11_ALLOCATOR) |
16 | #include <memory> |
17 | #endif |
18 | |
19 | namespace boost { |
20 | namespace detail { |
21 | typedef boost::true_type ms_is_trivial; |
22 | typedef boost::false_type ms_no_trivial; |
23 | |
24 | template<class T> |
25 | inline void ms_destroy(T*, std::size_t, ms_is_trivial) { |
26 | } |
27 | |
28 | template<class T> |
29 | inline void ms_destroy(T* memory, std::size_t size, ms_no_trivial) { |
30 | for (std::size_t i = size; i > 0;) { |
31 | memory[--i].~T(); |
32 | } |
33 | } |
34 | |
35 | template<class T> |
36 | inline void ms_destroy(T* memory, std::size_t size) { |
37 | boost::has_trivial_destructor<T> trivial; |
38 | ms_destroy(memory, size, trivial); |
39 | } |
40 | |
41 | template<class T> |
42 | inline void ms_init(T* memory, std::size_t size, ms_is_trivial) { |
43 | for (std::size_t i = 0; i < size; i++) { |
44 | void* p1 = memory + i; |
45 | ::new(p1) T(); |
46 | } |
47 | } |
48 | |
49 | template<class T> |
50 | inline void ms_init(T* memory, std::size_t size, ms_no_trivial) { |
51 | #if !defined(BOOST_NO_EXCEPTIONS) |
52 | std::size_t i = 0; |
53 | try { |
54 | for (; i < size; i++) { |
55 | void* p1 = memory + i; |
56 | ::new(p1) T(); |
57 | } |
58 | } catch (...) { |
59 | ms_destroy(memory, i); |
60 | throw; |
61 | } |
62 | #else |
63 | for (std::size_t i = 0; i < size; i++) { |
64 | void* p1 = memory + i; |
65 | ::new(p1) T(); |
66 | } |
67 | #endif |
68 | } |
69 | |
70 | template<class T> |
71 | inline void ms_init(T* memory, std::size_t size) { |
72 | boost::has_trivial_default_constructor<T> trivial; |
73 | ms_init(memory, size, trivial); |
74 | } |
75 | |
76 | template<class T, std::size_t N> |
77 | inline void ms_init(T* memory, std::size_t size, const T* list) { |
78 | #if !defined(BOOST_NO_EXCEPTIONS) |
79 | std::size_t i = 0; |
80 | try { |
81 | for (; i < size; i++) { |
82 | void* p1 = memory + i; |
83 | ::new(p1) T(list[i % N]); |
84 | } |
85 | } catch (...) { |
86 | ms_destroy(memory, i); |
87 | throw; |
88 | } |
89 | #else |
90 | for (std::size_t i = 0; i < size; i++) { |
91 | void* p1 = memory + i; |
92 | ::new(p1) T(list[i % N]); |
93 | } |
94 | #endif |
95 | } |
96 | |
97 | #if !defined(BOOST_NO_CXX11_ALLOCATOR) |
98 | template<class T, class A> |
99 | inline void as_destroy(const A& allocator, T* memory, |
100 | std::size_t size) { |
101 | typedef typename std::allocator_traits<A>:: |
102 | template rebind_alloc<T> TA; |
103 | typedef typename std::allocator_traits<A>:: |
104 | template rebind_traits<T> TT; |
105 | TA a2(allocator); |
106 | for (std::size_t i = size; i > 0;) { |
107 | TT::destroy(a2, &memory[--i]); |
108 | } |
109 | } |
110 | |
111 | template<class T, class A> |
112 | inline void as_init(const A& allocator, T* memory, std::size_t size, |
113 | ms_is_trivial) { |
114 | typedef typename std::allocator_traits<A>:: |
115 | template rebind_alloc<T> TA; |
116 | typedef typename std::allocator_traits<A>:: |
117 | template rebind_traits<T> TT; |
118 | TA a2(allocator); |
119 | for (std::size_t i = 0; i < size; i++) { |
120 | TT::construct(a2, memory + i); |
121 | } |
122 | } |
123 | |
124 | template<class T, class A> |
125 | inline void as_init(const A& allocator, T* memory, std::size_t size, |
126 | ms_no_trivial) { |
127 | typedef typename std::allocator_traits<A>:: |
128 | template rebind_alloc<T> TA; |
129 | typedef typename std::allocator_traits<A>:: |
130 | template rebind_traits<T> TT; |
131 | TA a2(allocator); |
132 | #if !defined(BOOST_NO_EXCEPTIONS) |
133 | std::size_t i = 0; |
134 | try { |
135 | for (; i < size; i++) { |
136 | TT::construct(a2, memory + i); |
137 | } |
138 | } catch (...) { |
139 | as_destroy(a2, memory, i); |
140 | throw; |
141 | } |
142 | #else |
143 | for (std::size_t i = 0; i < size; i++) { |
144 | TT::construct(a2, memory + i); |
145 | } |
146 | #endif |
147 | } |
148 | |
149 | template<class T, class A> |
150 | inline void as_init(const A& allocator, T* memory, std::size_t size) { |
151 | boost::has_trivial_default_constructor<T> trivial; |
152 | as_init(allocator, memory, size, trivial); |
153 | } |
154 | |
155 | template<class T, class A, std::size_t N> |
156 | inline void as_init(const A& allocator, T* memory, std::size_t size, |
157 | const T* list) { |
158 | typedef typename std::allocator_traits<A>:: |
159 | template rebind_alloc<T> TA; |
160 | typedef typename std::allocator_traits<A>:: |
161 | template rebind_traits<T> TT; |
162 | TA a2(allocator); |
163 | #if !defined(BOOST_NO_EXCEPTIONS) |
164 | std::size_t i = 0; |
165 | try { |
166 | for (; i < size; i++) { |
167 | TT::construct(a2, memory + i, list[i % N]); |
168 | } |
169 | } catch (...) { |
170 | as_destroy(a2, memory, i); |
171 | throw; |
172 | } |
173 | #else |
174 | for (std::size_t i = 0; i < size; i++) { |
175 | TT::construct(a2, memory + i, list[i % N]); |
176 | } |
177 | #endif |
178 | } |
179 | #endif |
180 | |
181 | template<class T> |
182 | inline void ms_noinit(T*, std::size_t, ms_is_trivial) { |
183 | } |
184 | |
185 | template<class T> |
186 | inline void ms_noinit(T* memory, std::size_t size, ms_no_trivial) { |
187 | #if !defined(BOOST_NO_EXCEPTIONS) |
188 | std::size_t i = 0; |
189 | try { |
190 | for (; i < size; i++) { |
191 | void* p1 = memory + i; |
192 | ::new(p1) T; |
193 | } |
194 | } catch (...) { |
195 | ms_destroy(memory, i); |
196 | throw; |
197 | } |
198 | #else |
199 | for (std::size_t i = 0; i < size; i++) { |
200 | void* p1 = memory + i; |
201 | ::new(p1) T; |
202 | } |
203 | #endif |
204 | } |
205 | |
206 | template<class T> |
207 | inline void ms_noinit(T* memory, std::size_t size) { |
208 | boost::has_trivial_default_constructor<T> trivial; |
209 | ms_noinit(memory, size, trivial); |
210 | } |
211 | } |
212 | } |
213 | |
214 | #endif |
215 | |