1257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier//===----------------------------------------------------------------------===// 2257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier// 3257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier// The LLVM Compiler Infrastructure 4257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier// 5257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier// This file is dual licensed under the MIT and the University of Illinois Open 6257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier// Source Licenses. See LICENSE.TXT for details. 7257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier// 8257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier//===----------------------------------------------------------------------===// 9257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier 10257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier#ifndef SUPPORT_TEST_MEMORY_RESOURCE_HPP 11257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier#define SUPPORT_TEST_MEMORY_RESOURCE_HPP 12257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier 13257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier#include <experimental/memory_resource> 14e386ad3090e7979c26c97a9a717624f8fc69d8f4Eric Fiselier#include <experimental/utility> 15257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier#include <memory> 16257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier#include <type_traits> 17257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier#include <cstddef> 18257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier#include <cstdlib> 19257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier#include <cstring> 202aad5d548c2b02bd8e07394a484ae857436c5b03Eric Fiselier#include <cstdint> 21257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier#include <cassert> 22257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier#include "test_macros.h" 23e386ad3090e7979c26c97a9a717624f8fc69d8f4Eric Fiselier#include "controlled_allocators.hpp" 24e386ad3090e7979c26c97a9a717624f8fc69d8f4Eric Fiselier#include "uses_alloc_types.hpp" 25e386ad3090e7979c26c97a9a717624f8fc69d8f4Eric Fiselier 26e386ad3090e7979c26c97a9a717624f8fc69d8f4Eric Fiselier// FIXME: This is a hack to allow uses_allocator_types.hpp to work with 27e386ad3090e7979c26c97a9a717624f8fc69d8f4Eric Fiselier// erased_type. However we can't define that behavior directly in the header 2816e2ba19dfffdcf9bba202eb8a27fd79e3d15303Stephan T. Lavavej// because it can't include <experimental/memory_resource> 29e386ad3090e7979c26c97a9a717624f8fc69d8f4Eric Fiseliertemplate <> 30e386ad3090e7979c26c97a9a717624f8fc69d8f4Eric Fiselierstruct TransformErasedTypeAlloc<std::experimental::erased_type> { 31e386ad3090e7979c26c97a9a717624f8fc69d8f4Eric Fiselier using type = std::experimental::pmr::memory_resource*; 32257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier}; 33257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier 34257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiseliertemplate <class ProviderT, int = 0> 35257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselierclass TestResourceImp : public std::experimental::pmr::memory_resource 36257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier{ 37257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselierpublic: 38257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier static int resource_alive; 39257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier static int resource_constructed; 40257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier static int resource_destructed; 41257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier 42257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier static void resetStatics() { 43257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier assert(resource_alive == 0); 44257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier resource_alive = 0; 45257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier resource_constructed = 0; 46257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier resource_destructed = 0; 47257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier } 48257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier 49257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier using memory_resource = std::experimental::pmr::memory_resource; 50257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier using Provider = ProviderT; 51257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier 52257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier int value; 53257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier 54257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier explicit TestResourceImp(int val = 0) : value(val) { 55257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier ++resource_alive; 56257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier ++resource_constructed; 57257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier } 58257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier 59257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier ~TestResourceImp() noexcept { 60257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier --resource_alive; 61257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier ++resource_destructed; 62257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier } 63257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier 64257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier void reset() { C.reset(); P.reset(); } 65257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier AllocController& getController() { return C; } 66257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier 67257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier bool checkAlloc(void* p, std::size_t s, std::size_t a) const 68257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier { return C.checkAlloc(p, s, a); } 69257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier 70257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier bool checkDealloc(void* p, std::size_t s, std::size_t a) const 71257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier { return C.checkDealloc(p, s, a); } 72257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier 73257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier bool checkIsEqualCalledEq(int n) const { return C.checkIsEqualCalledEq(n); } 74257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier 75257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselierprotected: 76257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier virtual void * do_allocate(std::size_t s, std::size_t a) { 77257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier if (C.throw_on_alloc) { 78257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier#ifndef TEST_HAS_NO_EXCEPTIONS 79257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier throw TestException{}; 80257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier#else 81257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier assert(false); 82257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier#endif 83257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier } 84257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier void* ret = P.allocate(s, a); 85257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier C.countAlloc(ret, s, a); 86257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier return ret; 87257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier } 88257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier 89257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier virtual void do_deallocate(void * p, std::size_t s, std::size_t a) { 90257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier C.countDealloc(p, s, a); 91257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier P.deallocate(p, s, a); 92257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier } 93257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier 94257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier virtual bool do_is_equal(memory_resource const & other) const noexcept { 95257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier C.countIsEqual(); 96257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier TestResourceImp const * o = dynamic_cast<TestResourceImp const *>(&other); 97257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier return o && o->value == value; 98257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier } 99257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselierprivate: 100257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier mutable AllocController C; 101257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier mutable Provider P; 102257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier DISALLOW_COPY(TestResourceImp); 103257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier}; 104257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier 105257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiseliertemplate <class Provider, int N> 106257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselierint TestResourceImp<Provider, N>::resource_alive = 0; 107257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier 108257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiseliertemplate <class Provider, int N> 109257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselierint TestResourceImp<Provider, N>::resource_constructed = 0; 110257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier 111257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiseliertemplate <class Provider, int N> 112257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselierint TestResourceImp<Provider, N>::resource_destructed = 0; 113257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier 114257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier 115257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselierstruct NullProvider { 116257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier NullProvider() {} 117257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier void* allocate(size_t, size_t) { return nullptr; } 118257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier void deallocate(void*, size_t, size_t) {} 119257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier void reset() {} 120257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselierprivate: 121257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier DISALLOW_COPY(NullProvider); 122257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier}; 123257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier 124257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselierstruct NewDeleteProvider { 125257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier NewDeleteProvider() {} 126257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier void* allocate(size_t s, size_t) { return ::operator new(s); } 127257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier void deallocate(void* p, size_t, size_t) { ::operator delete(p); } 128257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier void reset() {} 129257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselierprivate: 130257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier DISALLOW_COPY(NewDeleteProvider); 131257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier}; 132257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier 133257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiseliertemplate <size_t Size = 4096 * 10> // 10 pages worth of memory. 134257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselierstruct BufferProvider { 135257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier char buffer[Size]; 136257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier void* next = &buffer; 137257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier size_t space = Size; 138257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier 139257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier BufferProvider() {} 140257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier 141257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier void* allocate(size_t s, size_t a) { 142257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier void* ret = std::align(s, a, next, space); 143257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier if (ret == nullptr) { 144257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier#ifndef TEST_HAS_NO_EXCEPTIONS 145257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier throw std::bad_alloc(); 146257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier#else 147257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier assert(false); 148257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier#endif 149257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier } 150257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier 151257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier return ret; 152257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier } 153257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier 154257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier void deallocate(void*, size_t, size_t) {} 155257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier 156257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier void reset() { 157257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier next = &buffer; 158257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier space = Size; 159257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier } 160257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselierprivate: 161257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier DISALLOW_COPY(BufferProvider); 162257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier}; 163257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier 164257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselierusing NullResource = TestResourceImp<NullProvider, 0>; 165257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselierusing NewDeleteResource = TestResourceImp<NewDeleteProvider, 0>; 166257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselierusing TestResource = TestResourceImp<BufferProvider<>, 0>; 167257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselierusing TestResource1 = TestResourceImp<BufferProvider<>, 1>; 168257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselierusing TestResource2 = TestResourceImp<BufferProvider<>, 2>; 169257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier 170257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier 171257fd699fd62d09908944845fba04c4a9ab8d03bEric Fiselier#endif /* SUPPORT_TEST_MEMORY_RESOURCE_HPP */ 172