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
24struct repointable_resource : public std::pmr::memory_resource {
25 std::pmr::memory_resource* which;
26
27 explicit repointable_resource(std::pmr::memory_resource* res) : which(res) {}
28
29private:
30 void* do_allocate(std::size_t size, size_t align) override { return which->allocate(bytes: size, alignment: align); }
31
32 void do_deallocate(void* p, std::size_t size, size_t align) override { return which->deallocate(p: p, bytes: size, alignment: align); }
33
34 bool do_is_equal(std::pmr::memory_resource const& rhs) const noexcept override { return which->is_equal(other: rhs); }
35};
36
37void 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(bytes: 64, alignment: 16);
45 assert(res == buffer);
46 assert(globalMemCounter.checkNewCalledEq(0));
47
48 res = r1.allocate(bytes: 64, alignment: 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(bytes: last_new_size, alignment: 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(bytes: last_new_size, alignment: 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
75int 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

source code of libcxx/test/std/utilities/utility/mem.res/mem.res.monotonic.buffer/mem.res.monotonic.buffer.mem/allocate_exception_safety.pass.cpp