1243da90eSArthur O'Dwyer //===----------------------------------------------------------------------===// 2243da90eSArthur O'Dwyer // 3243da90eSArthur O'Dwyer // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4243da90eSArthur O'Dwyer // See https://llvm.org/LICENSE.txt for license information. 5243da90eSArthur O'Dwyer // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6243da90eSArthur O'Dwyer // 7243da90eSArthur O'Dwyer //===----------------------------------------------------------------------===// 8243da90eSArthur O'Dwyer 9243da90eSArthur O'Dwyer #ifndef SUPPORT_TEST_STD_MEMORY_RESOURCE_H 10243da90eSArthur O'Dwyer #define SUPPORT_TEST_STD_MEMORY_RESOURCE_H 11243da90eSArthur O'Dwyer 12243da90eSArthur O'Dwyer #include <memory> 13243da90eSArthur O'Dwyer #include <memory_resource> 14243da90eSArthur O'Dwyer #include <type_traits> 15243da90eSArthur O'Dwyer #include <utility> 16243da90eSArthur O'Dwyer #include <cstddef> 17243da90eSArthur O'Dwyer #include <cstdlib> 18243da90eSArthur O'Dwyer #include <cstring> 19243da90eSArthur O'Dwyer #include <cstdint> 20243da90eSArthur O'Dwyer #include <cassert> 21243da90eSArthur O'Dwyer #include "test_macros.h" 22243da90eSArthur O'Dwyer #include "controlled_allocators.h" 23243da90eSArthur O'Dwyer #include "uses_alloc_types.h" 24243da90eSArthur O'Dwyer 25243da90eSArthur O'Dwyer template <class ProviderT, int = 0> 26243da90eSArthur O'Dwyer class TestResourceImp : public std::pmr::memory_resource { 27243da90eSArthur O'Dwyer public: 28243da90eSArthur O'Dwyer static int resource_alive; 29243da90eSArthur O'Dwyer static int resource_constructed; 30243da90eSArthur O'Dwyer static int resource_destructed; 31243da90eSArthur O'Dwyer resetStatics()32243da90eSArthur O'Dwyer static void resetStatics() { 33243da90eSArthur O'Dwyer assert(resource_alive == 0); 34243da90eSArthur O'Dwyer resource_alive = 0; 35243da90eSArthur O'Dwyer resource_constructed = 0; 36243da90eSArthur O'Dwyer resource_destructed = 0; 37243da90eSArthur O'Dwyer } 38243da90eSArthur O'Dwyer 39243da90eSArthur O'Dwyer using memory_resource = std::pmr::memory_resource; 40243da90eSArthur O'Dwyer using Provider = ProviderT; 41243da90eSArthur O'Dwyer 42243da90eSArthur O'Dwyer int value; 43243da90eSArthur O'Dwyer value(val)44243da90eSArthur O'Dwyer explicit TestResourceImp(int val = 0) : value(val) { 45243da90eSArthur O'Dwyer ++resource_alive; 46243da90eSArthur O'Dwyer ++resource_constructed; 47243da90eSArthur O'Dwyer } 48243da90eSArthur O'Dwyer ~TestResourceImp()49243da90eSArthur O'Dwyer ~TestResourceImp() noexcept { 50243da90eSArthur O'Dwyer --resource_alive; 51243da90eSArthur O'Dwyer ++resource_destructed; 52243da90eSArthur O'Dwyer } 53243da90eSArthur O'Dwyer reset()54243da90eSArthur O'Dwyer void reset() { 55243da90eSArthur O'Dwyer C.reset(); 56243da90eSArthur O'Dwyer P.reset(); 57243da90eSArthur O'Dwyer } getController()58243da90eSArthur O'Dwyer AllocController& getController() { return C; } 59243da90eSArthur O'Dwyer checkAlloc(void * p,std::size_t s,std::size_t a)60243da90eSArthur O'Dwyer bool checkAlloc(void* p, std::size_t s, std::size_t a) const { return C.checkAlloc(p, s, a); } 61243da90eSArthur O'Dwyer checkDealloc(void * p,std::size_t s,std::size_t a)62243da90eSArthur O'Dwyer bool checkDealloc(void* p, std::size_t s, std::size_t a) const { return C.checkDealloc(p, s, a); } 63243da90eSArthur O'Dwyer checkIsEqualCalledEq(int n)64243da90eSArthur O'Dwyer bool checkIsEqualCalledEq(int n) const { return C.checkIsEqualCalledEq(n); } 65243da90eSArthur O'Dwyer 66243da90eSArthur O'Dwyer protected: do_allocate(std::size_t s,std::size_t a)67243da90eSArthur O'Dwyer virtual void* do_allocate(std::size_t s, std::size_t a) { 68243da90eSArthur O'Dwyer if (C.throw_on_alloc) { 69243da90eSArthur O'Dwyer #ifndef TEST_HAS_NO_EXCEPTIONS 70243da90eSArthur O'Dwyer throw TestException{}; 71243da90eSArthur O'Dwyer #else 72243da90eSArthur O'Dwyer assert(false); 73243da90eSArthur O'Dwyer #endif 74243da90eSArthur O'Dwyer } 75243da90eSArthur O'Dwyer void* ret = P.allocate(s, a); 76243da90eSArthur O'Dwyer C.countAlloc(ret, s, a); 77243da90eSArthur O'Dwyer return ret; 78243da90eSArthur O'Dwyer } 79243da90eSArthur O'Dwyer do_deallocate(void * p,std::size_t s,std::size_t a)80243da90eSArthur O'Dwyer virtual void do_deallocate(void* p, std::size_t s, std::size_t a) { 81243da90eSArthur O'Dwyer C.countDealloc(p, s, a); 82243da90eSArthur O'Dwyer P.deallocate(p, s, a); 83243da90eSArthur O'Dwyer } 84243da90eSArthur O'Dwyer do_is_equal(memory_resource const & other)85243da90eSArthur O'Dwyer virtual bool do_is_equal(memory_resource const& other) const noexcept { 86243da90eSArthur O'Dwyer C.countIsEqual(); 87243da90eSArthur O'Dwyer TestResourceImp const* o = dynamic_cast<TestResourceImp const*>(&other); 88243da90eSArthur O'Dwyer return o && o->value == value; 89243da90eSArthur O'Dwyer } 90243da90eSArthur O'Dwyer 91243da90eSArthur O'Dwyer private: 92243da90eSArthur O'Dwyer mutable AllocController C; 93243da90eSArthur O'Dwyer mutable Provider P; 94243da90eSArthur O'Dwyer DISALLOW_COPY(TestResourceImp); 95243da90eSArthur O'Dwyer }; 96243da90eSArthur O'Dwyer 97243da90eSArthur O'Dwyer template <class Provider, int N> 98243da90eSArthur O'Dwyer int TestResourceImp<Provider, N>::resource_alive = 0; 99243da90eSArthur O'Dwyer 100243da90eSArthur O'Dwyer template <class Provider, int N> 101243da90eSArthur O'Dwyer int TestResourceImp<Provider, N>::resource_constructed = 0; 102243da90eSArthur O'Dwyer 103243da90eSArthur O'Dwyer template <class Provider, int N> 104243da90eSArthur O'Dwyer int TestResourceImp<Provider, N>::resource_destructed = 0; 105243da90eSArthur O'Dwyer 106243da90eSArthur O'Dwyer struct NullProvider { NullProviderNullProvider107243da90eSArthur O'Dwyer NullProvider() {} allocateNullProvider108*fb855eb9SMark de Wever void* allocate(std::size_t, size_t) { 109f4ca5da2SNikolas Klauser #ifndef TEST_HAS_NO_EXCEPTIONS 110f4ca5da2SNikolas Klauser throw std::runtime_error(""); 111f4ca5da2SNikolas Klauser #else 112f4ca5da2SNikolas Klauser std::abort(); 113f4ca5da2SNikolas Klauser #endif 114f4ca5da2SNikolas Klauser } deallocateNullProvider115*fb855eb9SMark de Wever void deallocate(void*, std::size_t, size_t) {} resetNullProvider116243da90eSArthur O'Dwyer void reset() {} 117243da90eSArthur O'Dwyer 118243da90eSArthur O'Dwyer private: 119243da90eSArthur O'Dwyer DISALLOW_COPY(NullProvider); 120243da90eSArthur O'Dwyer }; 121243da90eSArthur O'Dwyer 122243da90eSArthur O'Dwyer struct NewDeleteProvider { NewDeleteProviderNewDeleteProvider123243da90eSArthur O'Dwyer NewDeleteProvider() {} allocateNewDeleteProvider124*fb855eb9SMark de Wever void* allocate(std::size_t s, size_t) { return ::operator new(s); } deallocateNewDeleteProvider125*fb855eb9SMark de Wever void deallocate(void* p, std::size_t, size_t) { ::operator delete(p); } resetNewDeleteProvider126243da90eSArthur O'Dwyer void reset() {} 127243da90eSArthur O'Dwyer 128243da90eSArthur O'Dwyer private: 129243da90eSArthur O'Dwyer DISALLOW_COPY(NewDeleteProvider); 130243da90eSArthur O'Dwyer }; 131243da90eSArthur O'Dwyer 132*fb855eb9SMark de Wever template <std::size_t Size = 4096 * 10> // 10 pages worth of memory. 133243da90eSArthur O'Dwyer struct BufferProvider { 134243da90eSArthur O'Dwyer char buffer[Size]; 135243da90eSArthur O'Dwyer void* next = &buffer; 136*fb855eb9SMark de Wever std::size_t space = Size; 137243da90eSArthur O'Dwyer BufferProviderBufferProvider138243da90eSArthur O'Dwyer BufferProvider() {} 139243da90eSArthur O'Dwyer allocateBufferProvider140*fb855eb9SMark de Wever void* allocate(std::size_t s, size_t a) { 141f4ca5da2SNikolas Klauser void* ret = std::align(a, s, next, space); 142243da90eSArthur O'Dwyer if (ret == nullptr) { 143243da90eSArthur O'Dwyer #ifndef TEST_HAS_NO_EXCEPTIONS 144243da90eSArthur O'Dwyer throw std::bad_alloc(); 145243da90eSArthur O'Dwyer #else 146243da90eSArthur O'Dwyer assert(false); 147243da90eSArthur O'Dwyer #endif 148243da90eSArthur O'Dwyer } 149243da90eSArthur O'Dwyer 150243da90eSArthur O'Dwyer return ret; 151243da90eSArthur O'Dwyer } 152243da90eSArthur O'Dwyer deallocateBufferProvider153*fb855eb9SMark de Wever void deallocate(void*, std::size_t, size_t) {} 154243da90eSArthur O'Dwyer resetBufferProvider155243da90eSArthur O'Dwyer void reset() { 156243da90eSArthur O'Dwyer next = &buffer; 157243da90eSArthur O'Dwyer space = Size; 158243da90eSArthur O'Dwyer } 159243da90eSArthur O'Dwyer 160243da90eSArthur O'Dwyer private: 161243da90eSArthur O'Dwyer DISALLOW_COPY(BufferProvider); 162243da90eSArthur O'Dwyer }; 163243da90eSArthur O'Dwyer 164243da90eSArthur O'Dwyer using NullResource = TestResourceImp<NullProvider, 0>; 165243da90eSArthur O'Dwyer using NewDeleteResource = TestResourceImp<NewDeleteProvider, 0>; 166243da90eSArthur O'Dwyer using TestResource = TestResourceImp<BufferProvider<>, 0>; 167243da90eSArthur O'Dwyer using TestResource1 = TestResourceImp<BufferProvider<>, 1>; 168243da90eSArthur O'Dwyer using TestResource2 = TestResourceImp<BufferProvider<>, 2>; 169243da90eSArthur O'Dwyer 170243da90eSArthur O'Dwyer #endif /* SUPPORT_TEST_STD_MEMORY_RESOURCE_H */ 171