xref: /llvm-project/libcxx/test/support/test_std_memory_resource.h (revision fb855eb941b6d740cc6560297d0b4d3201dcaf9f)
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