| // Copyright (C) 2018-2021 Free Software Foundation, Inc. |
| // |
| // This file is part of the GNU ISO C++ Library. This library is free |
| // software; you can redistribute it and/or modify it under the |
| // terms of the GNU General Public License as published by the |
| // Free Software Foundation; either version 3, or (at your option) |
| // any later version. |
| |
| // This library is distributed in the hope that it will be useful, |
| // but WITHOUT ANY WARRANTY; without even the implied warranty of |
| // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| // GNU General Public License for more details. |
| |
| // You should have received a copy of the GNU General Public License along |
| // with this library; see the file COPYING3. If not see |
| // <http://www.gnu.org/licenses/>. |
| |
| // { dg-do run { target c++14 } } |
| // { dg-require-cstdint "" } |
| |
| #include <experimental/memory_resource> |
| #include <cstdlib> |
| #include <cstdint> |
| #include <testsuite_hooks.h> |
| |
| #if (defined __sun__ || defined __VXWORKS__) && defined __i386__ |
| // See PR libstdc++/77691 |
| # define BAD_MAX_ALIGN_T 1 |
| #endif |
| |
| bool new_called = false; |
| bool delete_called = false; |
| std::size_t bytes_allocated = 0; |
| |
| void* operator new(std::size_t n) |
| { |
| new_called = true; |
| if (void* p = malloc(n)) |
| { |
| bytes_allocated += n; |
| return p; |
| } |
| throw std::bad_alloc(); |
| } |
| |
| void operator delete(void* p) noexcept |
| { |
| delete_called = true; |
| std::free(p); |
| bytes_allocated = 0; // assume everything getting deleted |
| } |
| |
| void operator delete(void* p, std::size_t n) noexcept |
| { |
| delete_called = true; |
| std::free(p); |
| bytes_allocated -= n; |
| } |
| |
| |
| template<std::size_t A> |
| bool aligned(void* p) |
| { return (reinterpret_cast<std::uintptr_t>(p) % A) == 0; } |
| |
| template<typename T> |
| bool aligned(void* p) |
| { return aligned<alignof(T)>(p); } |
| |
| // Extended alignments: |
| constexpr std::size_t al6 = (1ul << 6), al12 = (1ul << 12), al18 = (1ul << 18); |
| |
| using std::experimental::pmr::memory_resource; |
| using std::experimental::pmr::new_delete_resource; |
| |
| memory_resource* global = nullptr; |
| |
| void |
| test01() |
| { |
| memory_resource* r1 = new_delete_resource(); |
| VERIFY( *r1 == *r1 ); |
| memory_resource* r2 = new_delete_resource(); |
| VERIFY( r1 == r2 ); |
| VERIFY( *r1 == *r2 ); |
| global = r1; |
| } |
| |
| void |
| test02() |
| { |
| memory_resource* r1 = new_delete_resource(); |
| VERIFY( r1 == global ); |
| VERIFY( *r1 == *global ); |
| |
| new_called = false; |
| delete_called = false; |
| void* p = r1->allocate(1); |
| VERIFY( new_called ); |
| VERIFY( ! delete_called ); |
| |
| new_called = false; |
| r1->deallocate(p, 1); |
| VERIFY( ! new_called ); |
| VERIFY( delete_called ); |
| } |
| |
| void |
| test03() |
| { |
| using std::max_align_t; |
| using std::size_t; |
| void* p = nullptr; |
| |
| auto round = [](size_t n, size_t a) { return n % a ? n + a - (n % a) : n; }; |
| |
| bytes_allocated = 0; |
| |
| memory_resource* r1 = new_delete_resource(); |
| p = r1->allocate(1); // uses alignment = alignof(max_align_t) |
| #ifdef BAD_MAX_ALIGN_T |
| VERIFY( bytes_allocated != 0 ); |
| #else |
| VERIFY( bytes_allocated == alignof(max_align_t) ); |
| #endif |
| VERIFY( aligned<max_align_t>(p) ); |
| r1->deallocate(p, 1); |
| VERIFY( bytes_allocated == 0 ); |
| |
| p = r1->allocate(2, alignof(char)); |
| VERIFY( bytes_allocated == 2 ); |
| r1->deallocate(p, 2, alignof(char)); |
| VERIFY( bytes_allocated == 0 ); |
| |
| p = r1->allocate(3, alignof(short)); |
| VERIFY( bytes_allocated == round(3, alignof(short)) ); |
| VERIFY( aligned<short>(p) ); |
| r1->deallocate(p, 3, alignof(short)); |
| VERIFY( bytes_allocated == 0 ); |
| |
| p = r1->allocate(4, alignof(long)); |
| VERIFY( bytes_allocated == round(4, alignof(long)) ); |
| VERIFY( aligned<long>(p) ); |
| r1->deallocate(p, 4, alignof(long)); |
| VERIFY( bytes_allocated == 0 ); |
| |
| // Test extended aligments: |
| p = r1->allocate(777, al6); |
| VERIFY( bytes_allocated >= 777 ); |
| VERIFY( bytes_allocated < (777 + al6 + 8) ); // reasonable upper bound |
| VERIFY( aligned<al6>(p) ); |
| r1->deallocate(p, 777, al6); |
| VERIFY( bytes_allocated == 0 ); |
| |
| p = r1->allocate(888, al12); |
| VERIFY( bytes_allocated >= 888 ); |
| VERIFY( bytes_allocated < (888 + al12 + 8) ); // reasonable upper bound |
| VERIFY( aligned<al12>(p) ); |
| r1->deallocate(p, 888, al12); |
| VERIFY( bytes_allocated == 0 ); |
| |
| p = r1->allocate(999, al18); |
| VERIFY( bytes_allocated >= 999 ); |
| VERIFY( bytes_allocated < (999 + al18 + 8) ); // reasonable upper bound |
| VERIFY( aligned<al18>(p) ); |
| r1->deallocate(p, 999, al18); |
| VERIFY( bytes_allocated == 0 ); |
| } |
| |
| int main() |
| { |
| test01(); |
| test02(); |
| test03(); |
| } |