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 // UNSUPPORTED: c++03, c++11, c++14
10 // UNSUPPORTED: no-exceptions
11 // TODO: Change to XFAIL once https://github.com/llvm/llvm-project/issues/40340 is fixed
12 // UNSUPPORTED: availability-pmr-missing
13
14 // <memory_resource>
15
16 // class monotonic_buffer_resource
17
18 #include <memory_resource>
19 #include <cassert>
20
21 #include "count_new.h"
22 #include "test_macros.h"
23
24 struct repointable_resource : public std::pmr::memory_resource {
25 std::pmr::memory_resource* which;
26
repointable_resourcerepointable_resource27 explicit repointable_resource(std::pmr::memory_resource* res) : which(res) {}
28
29 private:
do_allocaterepointable_resource30 void* do_allocate(std::size_t size, size_t align) override { return which->allocate(size, align); }
31
do_deallocaterepointable_resource32 void do_deallocate(void* p, std::size_t size, size_t align) override { return which->deallocate(p, size, align); }
33
do_is_equalrepointable_resource34 bool do_is_equal(std::pmr::memory_resource const& rhs) const noexcept override { return which->is_equal(rhs); }
35 };
36
test_exception_safety()37 void test_exception_safety() {
38 globalMemCounter.reset();
39 auto upstream = repointable_resource(std::pmr::new_delete_resource());
40 alignas(16) char buffer[64];
41 auto mono1 = std::pmr::monotonic_buffer_resource(buffer, sizeof buffer, &upstream);
42 std::pmr::memory_resource& r1 = mono1;
43
44 void* res = r1.allocate(64, 16);
45 assert(res == buffer);
46 assert(globalMemCounter.checkNewCalledEq(0));
47
48 res = r1.allocate(64, 16);
49 assert(res != buffer);
50 assert(globalMemCounter.checkNewCalledEq(1));
51 assert(globalMemCounter.checkDeleteCalledEq(0));
52 const std::size_t last_new_size = globalMemCounter.last_new_size;
53
54 upstream.which = std::pmr::null_memory_resource();
55 try {
56 res = r1.allocate(last_new_size, 16);
57 assert(false);
58 } catch (const std::bad_alloc&) {
59 // we expect this
60 }
61 assert(globalMemCounter.checkNewCalledEq(1));
62 assert(globalMemCounter.checkDeleteCalledEq(0));
63
64 upstream.which = std::pmr::new_delete_resource();
65 res = r1.allocate(last_new_size, 16);
66 assert(res != buffer);
67 assert(globalMemCounter.checkNewCalledEq(2));
68 assert(globalMemCounter.checkDeleteCalledEq(0));
69
70 mono1.release();
71 assert(globalMemCounter.checkNewCalledEq(2));
72 assert(globalMemCounter.checkDeleteCalledEq(2));
73 }
74
main(int,char **)75 int main(int, char**) {
76 #if TEST_SUPPORTS_LIBRARY_INTERNAL_ALLOCATIONS && !defined(DISABLE_NEW_COUNT)
77 test_exception_safety();
78 #endif
79
80 return 0;
81 }
82