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