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