1 //===----------------------------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef MIN_ALLOCATOR_H 10 #define MIN_ALLOCATOR_H 11 12 #include <cstddef> 13 #include <cstdlib> 14 #include <cstddef> 15 #include <cassert> 16 #include <climits> 17 #include <memory> 18 19 #include "test_macros.h" 20 21 template <class T> 22 class bare_allocator 23 { 24 public: 25 typedef T value_type; 26 27 bare_allocator() TEST_NOEXCEPT {} 28 29 template <class U> 30 bare_allocator(bare_allocator<U>) TEST_NOEXCEPT {} 31 32 T* allocate(std::size_t n) 33 { 34 return static_cast<T*>(::operator new(n*sizeof(T))); 35 } 36 37 void deallocate(T* p, std::size_t) 38 { 39 return ::operator delete(static_cast<void*>(p)); 40 } 41 42 friend bool operator==(bare_allocator, bare_allocator) {return true;} 43 friend bool operator!=(bare_allocator x, bare_allocator y) {return !(x == y);} 44 }; 45 46 47 template <class T> 48 class no_default_allocator 49 { 50 #if TEST_STD_VER >= 11 51 no_default_allocator() = delete; 52 #else 53 no_default_allocator(); 54 #endif 55 struct construct_tag {}; 56 explicit no_default_allocator(construct_tag) {} 57 58 public: 59 static no_default_allocator create() { 60 construct_tag tag; 61 return no_default_allocator(tag); 62 } 63 64 public: 65 typedef T value_type; 66 67 template <class U> 68 no_default_allocator(no_default_allocator<U>) TEST_NOEXCEPT {} 69 70 T* allocate(std::size_t n) 71 { 72 return static_cast<T*>(::operator new(n*sizeof(T))); 73 } 74 75 void deallocate(T* p, std::size_t) 76 { 77 return ::operator delete(static_cast<void*>(p)); 78 } 79 80 friend bool operator==(no_default_allocator, no_default_allocator) {return true;} 81 friend bool operator!=(no_default_allocator x, no_default_allocator y) {return !(x == y);} 82 }; 83 84 struct malloc_allocator_base { 85 static size_t outstanding_bytes; 86 static size_t alloc_count; 87 static size_t dealloc_count; 88 static bool disable_default_constructor; 89 90 static size_t outstanding_alloc() { 91 assert(alloc_count >= dealloc_count); 92 return (alloc_count - dealloc_count); 93 } 94 95 static void reset() { 96 assert(outstanding_alloc() == 0); 97 disable_default_constructor = false; 98 outstanding_bytes = 0; 99 alloc_count = 0; 100 dealloc_count = 0; 101 } 102 }; 103 104 size_t malloc_allocator_base::outstanding_bytes = 0; 105 size_t malloc_allocator_base::alloc_count = 0; 106 size_t malloc_allocator_base::dealloc_count = 0; 107 bool malloc_allocator_base::disable_default_constructor = false; 108 109 110 template <class T> 111 class malloc_allocator : public malloc_allocator_base 112 { 113 public: 114 typedef T value_type; 115 116 malloc_allocator() TEST_NOEXCEPT { assert(!disable_default_constructor); } 117 118 template <class U> 119 malloc_allocator(malloc_allocator<U>) TEST_NOEXCEPT {} 120 121 T* allocate(std::size_t n) 122 { 123 const size_t nbytes = n*sizeof(T); 124 ++alloc_count; 125 outstanding_bytes += nbytes; 126 return static_cast<T*>(std::malloc(nbytes)); 127 } 128 129 void deallocate(T* p, std::size_t n) 130 { 131 const size_t nbytes = n*sizeof(T); 132 ++dealloc_count; 133 outstanding_bytes -= nbytes; 134 std::free(static_cast<void*>(p)); 135 } 136 137 friend bool operator==(malloc_allocator, malloc_allocator) {return true;} 138 friend bool operator!=(malloc_allocator x, malloc_allocator y) {return !(x == y);} 139 }; 140 141 template <class T> 142 struct cpp03_allocator : bare_allocator<T> 143 { 144 typedef T value_type; 145 typedef value_type* pointer; 146 147 static bool construct_called; 148 149 // Returned value is not used but it's not prohibited. 150 pointer construct(pointer p, const value_type& val) 151 { 152 ::new(p) value_type(val); 153 construct_called = true; 154 return p; 155 } 156 157 std::size_t max_size() const 158 { 159 return UINT_MAX / sizeof(T); 160 } 161 }; 162 template <class T> bool cpp03_allocator<T>::construct_called = false; 163 164 template <class T> 165 struct cpp03_overload_allocator : bare_allocator<T> 166 { 167 typedef T value_type; 168 typedef value_type* pointer; 169 170 static bool construct_called; 171 172 void construct(pointer p, const value_type& val) 173 { 174 construct(p, val, std::is_class<T>()); 175 } 176 void construct(pointer p, const value_type& val, std::true_type) 177 { 178 ::new(p) value_type(val); 179 construct_called = true; 180 } 181 void construct(pointer p, const value_type& val, std::false_type) 182 { 183 ::new(p) value_type(val); 184 construct_called = true; 185 } 186 187 std::size_t max_size() const 188 { 189 return UINT_MAX / sizeof(T); 190 } 191 }; 192 template <class T> bool cpp03_overload_allocator<T>::construct_called = false; 193 194 template <class T, class = std::integral_constant<size_t, 0> > class min_pointer; 195 template <class T, class ID> class min_pointer<const T, ID>; 196 template <class ID> class min_pointer<void, ID>; 197 template <class ID> class min_pointer<const void, ID>; 198 template <class T> class min_allocator; 199 200 template <class ID> 201 class min_pointer<const void, ID> 202 { 203 const void* ptr_; 204 public: 205 min_pointer() TEST_NOEXCEPT = default; 206 min_pointer(std::nullptr_t) TEST_NOEXCEPT : ptr_(nullptr) {} 207 template <class T> 208 min_pointer(min_pointer<T, ID> p) TEST_NOEXCEPT : ptr_(p.ptr_) {} 209 210 explicit operator bool() const {return ptr_ != nullptr;} 211 212 friend bool operator==(min_pointer x, min_pointer y) {return x.ptr_ == y.ptr_;} 213 friend bool operator!=(min_pointer x, min_pointer y) {return !(x == y);} 214 template <class U, class XID> friend class min_pointer; 215 }; 216 217 template <class ID> 218 class min_pointer<void, ID> 219 { 220 void* ptr_; 221 public: 222 min_pointer() TEST_NOEXCEPT = default; 223 min_pointer(std::nullptr_t) TEST_NOEXCEPT : ptr_(nullptr) {} 224 template <class T, 225 class = typename std::enable_if 226 < 227 !std::is_const<T>::value 228 >::type 229 > 230 min_pointer(min_pointer<T, ID> p) TEST_NOEXCEPT : ptr_(p.ptr_) {} 231 232 explicit operator bool() const {return ptr_ != nullptr;} 233 234 friend bool operator==(min_pointer x, min_pointer y) {return x.ptr_ == y.ptr_;} 235 friend bool operator!=(min_pointer x, min_pointer y) {return !(x == y);} 236 template <class U, class XID> friend class min_pointer; 237 }; 238 239 template <class T, class ID> 240 class min_pointer 241 { 242 T* ptr_; 243 244 explicit min_pointer(T* p) TEST_NOEXCEPT : ptr_(p) {} 245 public: 246 min_pointer() TEST_NOEXCEPT = default; 247 min_pointer(std::nullptr_t) TEST_NOEXCEPT : ptr_(nullptr) {} 248 explicit min_pointer(min_pointer<void, ID> p) TEST_NOEXCEPT : ptr_(static_cast<T*>(p.ptr_)) {} 249 250 explicit operator bool() const {return ptr_ != nullptr;} 251 252 typedef std::ptrdiff_t difference_type; 253 typedef T& reference; 254 typedef T* pointer; 255 typedef T value_type; 256 typedef std::random_access_iterator_tag iterator_category; 257 258 reference operator*() const {return *ptr_;} 259 pointer operator->() const {return ptr_;} 260 261 min_pointer& operator++() {++ptr_; return *this;} 262 min_pointer operator++(int) {min_pointer tmp(*this); ++ptr_; return tmp;} 263 264 min_pointer& operator--() {--ptr_; return *this;} 265 min_pointer operator--(int) {min_pointer tmp(*this); --ptr_; return tmp;} 266 267 min_pointer& operator+=(difference_type n) {ptr_ += n; return *this;} 268 min_pointer& operator-=(difference_type n) {ptr_ -= n; return *this;} 269 270 min_pointer operator+(difference_type n) const 271 { 272 min_pointer tmp(*this); 273 tmp += n; 274 return tmp; 275 } 276 277 friend min_pointer operator+(difference_type n, min_pointer x) 278 { 279 return x + n; 280 } 281 282 min_pointer operator-(difference_type n) const 283 { 284 min_pointer tmp(*this); 285 tmp -= n; 286 return tmp; 287 } 288 289 friend difference_type operator-(min_pointer x, min_pointer y) 290 { 291 return x.ptr_ - y.ptr_; 292 } 293 294 reference operator[](difference_type n) const {return ptr_[n];} 295 296 friend bool operator< (min_pointer x, min_pointer y) {return x.ptr_ < y.ptr_;} 297 friend bool operator> (min_pointer x, min_pointer y) {return y < x;} 298 friend bool operator<=(min_pointer x, min_pointer y) {return !(y < x);} 299 friend bool operator>=(min_pointer x, min_pointer y) {return !(x < y);} 300 301 static min_pointer pointer_to(T& t) {return min_pointer(std::addressof(t));} 302 303 friend bool operator==(min_pointer x, min_pointer y) {return x.ptr_ == y.ptr_;} 304 friend bool operator!=(min_pointer x, min_pointer y) {return !(x == y);} 305 template <class U, class XID> friend class min_pointer; 306 template <class U> friend class min_allocator; 307 }; 308 309 template <class T, class ID> 310 class min_pointer<const T, ID> 311 { 312 const T* ptr_; 313 314 explicit min_pointer(const T* p) : ptr_(p) {} 315 public: 316 min_pointer() TEST_NOEXCEPT = default; 317 min_pointer(std::nullptr_t) : ptr_(nullptr) {} 318 min_pointer(min_pointer<T, ID> p) : ptr_(p.ptr_) {} 319 explicit min_pointer(min_pointer<const void, ID> p) : ptr_(static_cast<const T*>(p.ptr_)) {} 320 321 explicit operator bool() const {return ptr_ != nullptr;} 322 323 typedef std::ptrdiff_t difference_type; 324 typedef const T& reference; 325 typedef const T* pointer; 326 typedef const T value_type; 327 typedef std::random_access_iterator_tag iterator_category; 328 329 reference operator*() const {return *ptr_;} 330 pointer operator->() const {return ptr_;} 331 332 min_pointer& operator++() {++ptr_; return *this;} 333 min_pointer operator++(int) {min_pointer tmp(*this); ++ptr_; return tmp;} 334 335 min_pointer& operator--() {--ptr_; return *this;} 336 min_pointer operator--(int) {min_pointer tmp(*this); --ptr_; return tmp;} 337 338 min_pointer& operator+=(difference_type n) {ptr_ += n; return *this;} 339 min_pointer& operator-=(difference_type n) {ptr_ -= n; return *this;} 340 341 min_pointer operator+(difference_type n) const 342 { 343 min_pointer tmp(*this); 344 tmp += n; 345 return tmp; 346 } 347 348 friend min_pointer operator+(difference_type n, min_pointer x) 349 { 350 return x + n; 351 } 352 353 min_pointer operator-(difference_type n) const 354 { 355 min_pointer tmp(*this); 356 tmp -= n; 357 return tmp; 358 } 359 360 friend difference_type operator-(min_pointer x, min_pointer y) 361 { 362 return x.ptr_ - y.ptr_; 363 } 364 365 reference operator[](difference_type n) const {return ptr_[n];} 366 367 friend bool operator< (min_pointer x, min_pointer y) {return x.ptr_ < y.ptr_;} 368 friend bool operator> (min_pointer x, min_pointer y) {return y < x;} 369 friend bool operator<=(min_pointer x, min_pointer y) {return !(y < x);} 370 friend bool operator>=(min_pointer x, min_pointer y) {return !(x < y);} 371 372 static min_pointer pointer_to(const T& t) {return min_pointer(std::addressof(t));} 373 374 friend bool operator==(min_pointer x, min_pointer y) {return x.ptr_ == y.ptr_;} 375 friend bool operator!=(min_pointer x, min_pointer y) {return !(x == y);} 376 template <class U, class XID> friend class min_pointer; 377 }; 378 379 template <class T, class ID> 380 inline 381 bool 382 operator==(min_pointer<T, ID> x, std::nullptr_t) 383 { 384 return !static_cast<bool>(x); 385 } 386 387 template <class T, class ID> 388 inline 389 bool 390 operator==(std::nullptr_t, min_pointer<T, ID> x) 391 { 392 return !static_cast<bool>(x); 393 } 394 395 template <class T, class ID> 396 inline 397 bool 398 operator!=(min_pointer<T, ID> x, std::nullptr_t) 399 { 400 return static_cast<bool>(x); 401 } 402 403 template <class T, class ID> 404 inline 405 bool 406 operator!=(std::nullptr_t, min_pointer<T, ID> x) 407 { 408 return static_cast<bool>(x); 409 } 410 411 template <class T> 412 class min_allocator 413 { 414 public: 415 typedef T value_type; 416 typedef min_pointer<T> pointer; 417 418 min_allocator() = default; 419 template <class U> 420 min_allocator(min_allocator<U>) {} 421 422 pointer allocate(std::ptrdiff_t n) 423 { 424 return pointer(static_cast<T*>(::operator new(n*sizeof(T)))); 425 } 426 427 void deallocate(pointer p, std::ptrdiff_t) 428 { 429 return ::operator delete(p.ptr_); 430 } 431 432 friend bool operator==(min_allocator, min_allocator) {return true;} 433 friend bool operator!=(min_allocator x, min_allocator y) {return !(x == y);} 434 }; 435 436 template <class T> 437 class explicit_allocator 438 { 439 public: 440 typedef T value_type; 441 442 explicit_allocator() TEST_NOEXCEPT {} 443 444 template <class U> 445 explicit explicit_allocator(explicit_allocator<U>) TEST_NOEXCEPT {} 446 447 T* allocate(std::size_t n) 448 { 449 return static_cast<T*>(::operator new(n*sizeof(T))); 450 } 451 452 void deallocate(T* p, std::size_t) 453 { 454 return ::operator delete(static_cast<void*>(p)); 455 } 456 457 friend bool operator==(explicit_allocator, explicit_allocator) {return true;} 458 friend bool operator!=(explicit_allocator x, explicit_allocator y) {return !(x == y);} 459 }; 460 461 #endif // MIN_ALLOCATOR_H 462