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 SUPPORT_TEST_STD_MEMORY_RESOURCE_H 10 #define SUPPORT_TEST_STD_MEMORY_RESOURCE_H 11 12 #include <memory> 13 #include <memory_resource> 14 #include <type_traits> 15 #include <utility> 16 #include <cstddef> 17 #include <cstdlib> 18 #include <cstring> 19 #include <cstdint> 20 #include <cassert> 21 #include "test_macros.h" 22 #include "controlled_allocators.h" 23 #include "uses_alloc_types.h" 24 25 template <class ProviderT, int = 0> 26 class TestResourceImp : public std::pmr::memory_resource { 27 public: 28 static int resource_alive; 29 static int resource_constructed; 30 static int resource_destructed; 31 32 static void resetStatics() { 33 assert(resource_alive == 0); 34 resource_alive = 0; 35 resource_constructed = 0; 36 resource_destructed = 0; 37 } 38 39 using memory_resource = std::pmr::memory_resource; 40 using Provider = ProviderT; 41 42 int value; 43 44 explicit TestResourceImp(int val = 0) : value(val) { 45 ++resource_alive; 46 ++resource_constructed; 47 } 48 49 ~TestResourceImp() noexcept { 50 --resource_alive; 51 ++resource_destructed; 52 } 53 54 void reset() { 55 C.reset(); 56 P.reset(); 57 } 58 AllocController& getController() { return C; } 59 60 bool checkAlloc(void* p, std::size_t s, std::size_t a) const { return C.checkAlloc(p, s, a); } 61 62 bool checkDealloc(void* p, std::size_t s, std::size_t a) const { return C.checkDealloc(p, s, a); } 63 64 bool checkIsEqualCalledEq(int n) const { return C.checkIsEqualCalledEq(n); } 65 66 protected: 67 virtual void* do_allocate(std::size_t s, std::size_t a) { 68 if (C.throw_on_alloc) { 69 #ifndef TEST_HAS_NO_EXCEPTIONS 70 throw TestException{}; 71 #else 72 assert(false); 73 #endif 74 } 75 void* ret = P.allocate(s, a); 76 C.countAlloc(ret, s, a); 77 return ret; 78 } 79 80 virtual void do_deallocate(void* p, std::size_t s, std::size_t a) { 81 C.countDealloc(p, s, a); 82 P.deallocate(p, s, a); 83 } 84 85 virtual bool do_is_equal(memory_resource const& other) const noexcept { 86 C.countIsEqual(); 87 TestResourceImp const* o = dynamic_cast<TestResourceImp const*>(&other); 88 return o && o->value == value; 89 } 90 91 private: 92 mutable AllocController C; 93 mutable Provider P; 94 DISALLOW_COPY(TestResourceImp); 95 }; 96 97 template <class Provider, int N> 98 int TestResourceImp<Provider, N>::resource_alive = 0; 99 100 template <class Provider, int N> 101 int TestResourceImp<Provider, N>::resource_constructed = 0; 102 103 template <class Provider, int N> 104 int TestResourceImp<Provider, N>::resource_destructed = 0; 105 106 struct NullProvider { 107 NullProvider() {} 108 void* allocate(size_t, size_t) { return nullptr; } 109 void deallocate(void*, size_t, size_t) {} 110 void reset() {} 111 112 private: 113 DISALLOW_COPY(NullProvider); 114 }; 115 116 struct NewDeleteProvider { 117 NewDeleteProvider() {} 118 void* allocate(size_t s, size_t) { return ::operator new(s); } 119 void deallocate(void* p, size_t, size_t) { ::operator delete(p); } 120 void reset() {} 121 122 private: 123 DISALLOW_COPY(NewDeleteProvider); 124 }; 125 126 template <size_t Size = 4096 * 10> // 10 pages worth of memory. 127 struct BufferProvider { 128 char buffer[Size]; 129 void* next = &buffer; 130 size_t space = Size; 131 132 BufferProvider() {} 133 134 void* allocate(size_t s, size_t a) { 135 void* ret = std::align(s, a, next, space); 136 if (ret == nullptr) { 137 #ifndef TEST_HAS_NO_EXCEPTIONS 138 throw std::bad_alloc(); 139 #else 140 assert(false); 141 #endif 142 } 143 144 return ret; 145 } 146 147 void deallocate(void*, size_t, size_t) {} 148 149 void reset() { 150 next = &buffer; 151 space = Size; 152 } 153 154 private: 155 DISALLOW_COPY(BufferProvider); 156 }; 157 158 using NullResource = TestResourceImp<NullProvider, 0>; 159 using NewDeleteResource = TestResourceImp<NewDeleteProvider, 0>; 160 using TestResource = TestResourceImp<BufferProvider<>, 0>; 161 using TestResource1 = TestResourceImp<BufferProvider<>, 1>; 162 using TestResource2 = TestResourceImp<BufferProvider<>, 2>; 163 164 #endif /* SUPPORT_TEST_STD_MEMORY_RESOURCE_H */ 165