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