Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 264 lines (217 sloc) 6.707 kB
27494a2 @jdelong Pull from FB rev 63ce89e2f2301e6bba44a111cc7d4218022156f6
jdelong authored
1 /*
cc86cd3 @juchem Implementing unique/shared_ptr for custom allocators (like Arena) in …
juchem authored
2 * Copyright 2013 Facebook, Inc.
27494a2 @jdelong Pull from FB rev 63ce89e2f2301e6bba44a111cc7d4218022156f6
jdelong authored
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef FOLLY_STLALLOCATOR_H_
18 #define FOLLY_STLALLOCATOR_H_
19
cc86cd3 @juchem Implementing unique/shared_ptr for custom allocators (like Arena) in …
juchem authored
20 #include "folly/Traits.h"
21
27494a2 @jdelong Pull from FB rev 63ce89e2f2301e6bba44a111cc7d4218022156f6
jdelong authored
22 #include <memory>
cc86cd3 @juchem Implementing unique/shared_ptr for custom allocators (like Arena) in …
juchem authored
23 #include <limits>
24 #include <utility>
25 #include <exception>
26 #include <stdexcept>
27
28 #include <cstddef>
27494a2 @jdelong Pull from FB rev 63ce89e2f2301e6bba44a111cc7d4218022156f6
jdelong authored
29
30 namespace folly {
31
32 /**
cc86cd3 @juchem Implementing unique/shared_ptr for custom allocators (like Arena) in …
juchem authored
33 * Wrap a SimpleAllocator into a STL-compliant allocator.
27494a2 @jdelong Pull from FB rev 63ce89e2f2301e6bba44a111cc7d4218022156f6
jdelong authored
34 *
cc86cd3 @juchem Implementing unique/shared_ptr for custom allocators (like Arena) in …
juchem authored
35 * The SimpleAllocator must provide two methods:
27494a2 @jdelong Pull from FB rev 63ce89e2f2301e6bba44a111cc7d4218022156f6
jdelong authored
36 * void* allocate(size_t size);
37 * void deallocate(void* ptr, size_t size);
38 * which, respectively, allocate a block of size bytes (aligned to the maximum
39 * alignment required on your system), throwing std::bad_alloc if the
40 * allocation can't be satisfied, and free a previously allocated block.
41 *
42 * Note that the following allocator resembles the standard allocator
43 * quite well:
44 *
45 * class MallocAllocator {
46 * public:
47 * void* allocate(size_t size) {
48 * void* p = malloc(size);
49 * if (!p) throw std::bad_alloc();
50 * return p;
51 * }
52 * void deallocate(void* p) {
53 * free(p);
54 * }
55 * };
cc86cd3 @juchem Implementing unique/shared_ptr for custom allocators (like Arena) in …
juchem authored
56 *
57 * author: Tudor Bosman <tudorb@fb.com>
27494a2 @jdelong Pull from FB rev 63ce89e2f2301e6bba44a111cc7d4218022156f6
jdelong authored
58 */
59
60 // This would be so much simpler with std::allocator_traits, but gcc 4.6.2
61 // doesn't support it
62 template <class Alloc, class T> class StlAllocator;
63
64 template <class Alloc> class StlAllocator<Alloc, void> {
65 public:
66 typedef void value_type;
67 typedef void* pointer;
68 typedef const void* const_pointer;
69 template <class U> struct rebind {
70 typedef StlAllocator<Alloc, U> other;
71 };
72 };
73
74 template <class Alloc, class T>
75 class StlAllocator {
76 public:
77 typedef T value_type;
78 typedef T* pointer;
79 typedef const T* const_pointer;
80 typedef T& reference;
81 typedef const T& const_reference;
82
83 typedef ptrdiff_t difference_type;
84 typedef size_t size_type;
85
86 StlAllocator() : alloc_(nullptr) { }
87 explicit StlAllocator(Alloc* alloc) : alloc_(alloc) { }
88
89 template <class U> StlAllocator(const StlAllocator<Alloc, U>& other)
90 : alloc_(other.alloc()) { }
91
92 T* allocate(size_t n, const void* hint = nullptr) {
93 return static_cast<T*>(alloc_->allocate(n * sizeof(T)));
94 }
95
96 void deallocate(T* p, size_t n) {
97 alloc_->deallocate(p);
98 }
99
100 size_t max_size() const {
101 return std::numeric_limits<size_t>::max();
102 }
103
104 T* address(T& x) const {
105 return std::addressof(x);
106 }
107
108 const T* address(const T& x) const {
109 return std::addressof(x);
110 }
111
112 template <class... Args>
113 void construct(T* p, Args&&... args) {
114 new (p) T(std::forward<Args>(args)...);
115 }
116
117 void destroy(T* p) {
118 p->~T();
119 }
120
121 Alloc* alloc() const {
122 return alloc_;
123 }
124
125 template <class U> struct rebind {
126 typedef StlAllocator<Alloc, U> other;
127 };
128
0286cb3 Add operator== and operator!= to folly::StlAllocator
Xiaoyang Gao authored
129 bool operator!=(const StlAllocator<Alloc, T>& other) const {
130 return alloc_ != other.alloc_;
131 }
132
133 bool operator==(const StlAllocator<Alloc, T>& other) const {
134 return alloc_ == other.alloc_;
135 }
136
27494a2 @jdelong Pull from FB rev 63ce89e2f2301e6bba44a111cc7d4218022156f6
jdelong authored
137 private:
138 Alloc* alloc_;
139 };
140
cc86cd3 @juchem Implementing unique/shared_ptr for custom allocators (like Arena) in …
juchem authored
141 /*
142 * Helper classes/functions for creating a unique_ptr using a custom allocator
143 *
144 * @author: Marcelo Juchem <marcelo@fb.com>
145 */
146
147 // A deleter implementation based on std::default_delete,
148 // which uses a custom allocator to free memory
149 template <typename Allocator>
150 class allocator_delete {
151 typedef typename std::remove_reference<Allocator>::type allocator_type;
152
153 public:
154 allocator_delete() = default;
155
156 explicit allocator_delete(const allocator_type& allocator):
157 allocator_(allocator)
158 {}
159
160 explicit allocator_delete(allocator_type&& allocator):
161 allocator_(std::move(allocator))
162 {}
163
164 template <typename U>
165 allocator_delete(const allocator_delete<U>& other):
166 allocator_(other.get_allocator())
167 {}
168
169 allocator_type& get_allocator() const {
170 return allocator_;
171 }
172
173 void operator()(typename allocator_type::pointer p) const {
174 if (!p) {
175 return;
176 }
177
178 allocator_.destroy(p);
179 allocator_.deallocate(p, 1);
180 }
181
182 private:
183 mutable allocator_type allocator_;
184 };
185
186 template <typename T, typename Allocator>
187 class is_simple_allocator {
188 FOLLY_CREATE_HAS_MEMBER_FN_TRAITS(has_destroy, destroy);
189
190 typedef typename std::remove_const<
191 typename std::remove_reference<Allocator>::type
192 >::type allocator;
193 typedef T value_type;
194 typedef value_type* pointer;
195
196 public:
197 constexpr static bool value = !has_destroy<allocator, void(pointer)>::value
198 && !has_destroy<allocator, void(void*)>::value;
199 };
200
201 template <typename T, typename Allocator>
202 typename std::enable_if<
203 is_simple_allocator<T, Allocator>::value,
204 folly::StlAllocator<typename std::remove_reference<Allocator>::type, T>
205 >::type make_stl_allocator(Allocator&& allocator) {
206 return folly::StlAllocator<
207 typename std::remove_reference<Allocator>::type, T
208 >(&allocator);
209 }
210
211 template <typename T, typename Allocator>
212 typename std::enable_if<
213 !is_simple_allocator<T, Allocator>::value,
214 typename std::remove_reference<Allocator>::type
215 >::type make_stl_allocator(Allocator&& allocator) {
216 return std::move(allocator);
217 }
218
219 template <typename T, typename Allocator>
220 struct AllocatorUniquePtr {
221 typedef std::unique_ptr<T,
222 folly::allocator_delete<
223 typename std::conditional<
224 is_simple_allocator<T, Allocator>::value,
225 folly::StlAllocator<typename std::remove_reference<Allocator>::type, T>,
226 typename std::remove_reference<Allocator>::type
227 >::type
228 >
229 > type;
230 };
231
232 template <typename T, typename Allocator, typename ...Args>
233 typename AllocatorUniquePtr<T, Allocator>::type allocate_unique(
234 Allocator&& allocator, Args&&... args
235 ) {
236 auto stlAllocator = folly::make_stl_allocator<T>(
237 std::forward<Allocator>(allocator)
238 );
239 auto p = stlAllocator.allocate(1);
240
241 try {
242 stlAllocator.construct(p, std::forward<Args>(args)...);
243
244 return {p,
245 folly::allocator_delete<decltype(stlAllocator)>(std::move(stlAllocator))
246 };
247 } catch (...) {
248 stlAllocator.deallocate(p, 1);
249 throw;
250 }
251 }
252
253 template <typename T, typename Allocator, typename ...Args>
254 std::shared_ptr<T> allocate_shared(Allocator&& allocator, Args&&... args) {
255 return std::allocate_shared<T>(
256 folly::make_stl_allocator<T>(std::forward<Allocator>(allocator)),
257 std::forward<Args>(args)...
258 );
259 }
260
27494a2 @jdelong Pull from FB rev 63ce89e2f2301e6bba44a111cc7d4218022156f6
jdelong authored
261 } // namespace folly
262
263 #endif /* FOLLY_STLALLOCATOR_H_ */
Something went wrong with that request. Please try again.