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