• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/boostorg/beast
8 //
9 
10 #ifndef BOOST_BEAST_TEST_TEST_ALLOCATOR_HPP
11 #define BOOST_BEAST_TEST_TEST_ALLOCATOR_HPP
12 
13 #include <atomic>
14 #include <cstddef>
15 #include <cstdint>
16 #include <memory>
17 
18 namespace boost {
19 namespace beast {
20 namespace test {
21 
22 struct test_allocator_info
23 {
24     std::size_t id;
25     std::size_t ncopy = 0;
26     std::size_t nmove = 0;
27     std::size_t nmassign = 0;
28     std::size_t ncpassign = 0;
29     std::size_t nselect = 0;
30     std::size_t max_size = (
31         std::numeric_limits<std::size_t>::max)();
32 
test_allocator_infoboost::beast::test::test_allocator_info33     test_allocator_info()
34         : id([]
35             {
36                 static std::atomic<std::size_t> sid(0);
37                 return ++sid;
38             }())
39     {
40     }
41 };
42 
43 template<
44     class T,
45     bool Equal,
46     bool Assign,
47     bool Move,
48     bool Swap,
49     bool Select>
50 class test_allocator;
51 
52 template<
53     class T,
54     bool Equal,
55     bool Assign,
56     bool Move,
57     bool Swap,
58     bool Select>
59 struct test_allocator_base
60 {
61 };
62 
63 // Select == true
64 template<
65     class T,
66     bool Equal,
67     bool Assign,
68     bool Move,
69     bool Swap>
70 struct test_allocator_base<
71     T, Equal, Assign, Move, Swap, true>
72 {
73     static
74     test_allocator<T, Equal, Assign, Move, Swap, true>
select_on_container_copy_constructionboost::beast::test::test_allocator_base75     select_on_container_copy_construction(test_allocator<
76         T, Equal, Assign, Move, Swap, true> const&)
77     {
78         return test_allocator<T,
79             Equal, Assign, Move, Swap, true>{};
80     }
81 };
82 
83 template<
84     class T,
85     bool Equal,
86     bool Assign,
87     bool Move,
88     bool Swap,
89     bool Select>
90 class test_allocator
91     : public test_allocator_base<
92         T, Equal, Assign, Move, Swap, Select>
93 {
94     std::shared_ptr<test_allocator_info> info_;
95 
96     template<class, bool, bool, bool, bool, bool>
97     friend class test_allocator;
98 
99 public:
100     using value_type = T;
101 
102     using propagate_on_container_copy_assignment =
103         std::integral_constant<bool, Assign>;
104 
105     using propagate_on_container_move_assignment =
106         std::integral_constant<bool, Move>;
107 
108     using propagate_on_container_swap =
109         std::integral_constant<bool, Swap>;
110 
111     template<class U>
112     struct rebind
113     {
114         using other = test_allocator<U, Equal, Assign, Move, Swap, Select>;
115     };
116 
test_allocator()117     test_allocator()
118         : info_(std::make_shared<
119             test_allocator_info>())
120     {
121     }
122 
test_allocator(test_allocator const & u)123     test_allocator(test_allocator const& u) noexcept
124         : info_(u.info_)
125     {
126         ++info_->ncopy;
127     }
128 
129     template<class U>
test_allocator(test_allocator<U,Equal,Assign,Move,Swap,Select> const & u)130     test_allocator(test_allocator<U,
131             Equal, Assign, Move, Swap, Select> const& u) noexcept
132         : info_(u.info_)
133     {
134         ++info_->ncopy;
135     }
136 
test_allocator(test_allocator && t)137     test_allocator(test_allocator&& t)
138         : info_(t.info_)
139     {
140         ++info_->nmove;
141     }
142 
143     test_allocator&
operator =(test_allocator const & u)144     operator=(test_allocator const& u) noexcept
145     {
146         info_ = u.info_;
147         ++info_->ncpassign;
148         return *this;
149     }
150 
151     test_allocator&
operator =(test_allocator && u)152     operator=(test_allocator&& u) noexcept
153     {
154         info_ = u.info_;
155         ++info_->nmassign;
156         return *this;
157     }
158 
159     value_type*
allocate(std::size_t n)160     allocate(std::size_t n)
161     {
162         return static_cast<value_type*>(
163             ::operator new (n*sizeof(value_type)));
164     }
165 
166     void
deallocate(value_type * p,std::size_t)167     deallocate(value_type* p, std::size_t) noexcept
168     {
169         ::operator delete(p);
170     }
171 
172     std::size_t
max_size() const173     max_size() const
174     {
175         return info_->max_size;
176     }
177 
178     void
max_size(std::size_t n)179     max_size(std::size_t n)
180     {
181         info_->max_size = n;
182     }
183 
184     bool
operator ==(test_allocator const & other) const185     operator==(test_allocator const& other) const
186     {
187         return id() == other.id() || Equal;
188     }
189 
190     bool
operator !=(test_allocator const & other) const191     operator!=(test_allocator const& other) const
192     {
193         return ! this->operator==(other);
194     }
195 
196     std::size_t
id() const197     id() const
198     {
199         return info_->id;
200     }
201 
202     test_allocator_info*
operator ->() const203     operator->() const
204     {
205         return info_.get();
206     }
207 };
208 
209 //------------------------------------------------------------------------------
210 
211 #if 0
212 struct allocator_info
213 {
214     std::size_t const id;
215 
216     allocator_info()
217         : id([]
218             {
219                 static std::atomic<std::size_t> sid(0);
220                 return ++sid;
221             }())
222     {
223     }
224 };
225 
226 struct allocator_defaults
227 {
228     static std::size_t constexpr max_size =
229         (std::numeric_limits<std::size_t>::max)();
230 };
231 
232 template<
233     class T,
234     class Traits = allocator_defaults>
235 struct allocator
236 {
237 public:
238     using value_type = T;
239 
240 #if 0
241     template<class U>
242     struct rebind
243     {
244         using other =
245             test_allocator<U, Traits>;
246     };
247 #endif
248 
249     allocator() = default;
250     allocator(allocator&& t) = default;
251     allocator(allocator const& u) = default;
252 
253     template<
254         class U,
255         class = typename std::enable_if<
256             ! std::is_same<U, T>::value>::type>
257     allocator(
258         allocator<U, Traits> const& u) noexcept
259     {
260     }
261 
262     allocator&
263     operator=(allocator&& u) noexcept
264     {
265         return *this;
266     }
267 
268     allocator&
269     operator=(allocator const& u) noexcept
270     {
271         return *this;
272     }
273 
274     value_type*
275     allocate(std::size_t n)
276     {
277         return static_cast<value_type*>(
278             ::operator new(n * sizeof(value_type)));
279     }
280 
281     void
282     deallocate(value_type* p, std::size_t) noexcept
283     {
284         ::operator delete(p);
285     }
286 
287     std::size_t
288     max_size() const
289     {
290     }
291 
292     bool
293     operator==(test_allocator const& other) const
294     {
295         return id() == other.id() || Equal;
296     }
297 
298     bool
299     operator!=(test_allocator const& other) const
300     {
301         return ! this->operator==(other);
302     }
303 };
304 #endif
305 
306 } // test
307 } // beast
308 } // boost
309 
310 #endif
311