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: no-exceptions
10// UNSUPPORTED: c++03, c++11, c++14
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 synchronized_pool_resource
17
18#include <algorithm>
19#include <cassert>
20#include <cstddef>
21#include <memory_resource>
22#include <new>
23#include <vector>
24
25struct allocation_record {
26 std::size_t bytes;
27 std::size_t align;
28 explicit allocation_record(std::size_t b, size_t a) : bytes(b), align(a) {}
29 bool operator==(const allocation_record& rhs) const { return (bytes == rhs.bytes) && (align == rhs.align); }
30 bool operator<(const allocation_record& rhs) const {
31 if (bytes != rhs.bytes)
32 return (bytes < rhs.bytes);
33 return (align < rhs.align);
34 }
35};
36
37class test_resource : public std::pmr::memory_resource {
38 void* do_allocate(std::size_t bytes, size_t align) override {
39 void* result = std::pmr::new_delete_resource()->allocate(bytes: bytes, alignment: align);
40 successful_allocations.emplace_back(args&: bytes, args&: align);
41 return result;
42 }
43 void do_deallocate(void* p, std::size_t bytes, size_t align) override {
44 deallocations.emplace_back(args&: bytes, args&: align);
45 return std::pmr::new_delete_resource()->deallocate(p: p, bytes: bytes, alignment: align);
46 }
47 bool do_is_equal(const std::pmr::memory_resource&) const noexcept override { return false; }
48
49public:
50 std::vector<allocation_record> successful_allocations;
51 std::vector<allocation_record> deallocations;
52};
53
54template <class F>
55void test_allocation_pattern(F do_pattern) {
56 test_resource tr;
57 std::pmr::pool_options opts{.max_blocks_per_chunk: 0, .largest_required_pool_block: 256};
58 std::pmr::synchronized_pool_resource spr(opts, &tr);
59
60 try {
61 do_pattern(spr);
62 } catch (const std::bad_alloc&) {
63 }
64 spr.release();
65
66 assert(tr.successful_allocations.size() == tr.deallocations.size());
67 assert(std::is_permutation(
68 tr.successful_allocations.begin(),
69 tr.successful_allocations.end(),
70 tr.deallocations.begin(),
71 tr.deallocations.end()));
72}
73
74template <std::size_t Bytes, size_t Align>
75auto foo() {
76 return [=](auto& mr) {
77 void* p = mr.allocate(Bytes, Align);
78 mr.deallocate(p, Bytes, Align);
79 };
80}
81
82int main(int, char**) {
83 test_allocation_pattern(do_pattern: foo<2, 1>());
84 test_allocation_pattern(do_pattern: foo<2, 8>());
85 test_allocation_pattern(do_pattern: foo<2, 64>());
86 test_allocation_pattern(do_pattern: foo<128, 1>());
87 test_allocation_pattern(do_pattern: foo<128, 8>());
88 test_allocation_pattern(do_pattern: foo<128, 64>());
89 test_allocation_pattern(do_pattern: foo<1024, 1>());
90 test_allocation_pattern(do_pattern: foo<1024, 8>());
91 test_allocation_pattern(do_pattern: foo<1024, 64>());
92
93 test_allocation_pattern(do_pattern: [](auto& mr) {
94 void* p1 = mr.allocate(2, 1);
95 void* p2 = mr.allocate(2, 8);
96 void* p3 = mr.allocate(2, 64);
97 void* p4 = mr.allocate(128, 1);
98 void* p5 = mr.allocate(128, 8);
99 void* p6 = mr.allocate(128, 64);
100 void* p7 = mr.allocate(1024, 1);
101 void* p8 = mr.allocate(1024, 8);
102 void* p9 = mr.allocate(1024, 64);
103 mr.deallocate(p1, 2, 1);
104 mr.deallocate(p2, 2, 8);
105 mr.deallocate(p3, 2, 64);
106 mr.deallocate(p4, 128, 1);
107 mr.deallocate(p5, 128, 8);
108 mr.deallocate(p6, 128, 64);
109 mr.deallocate(p7, 1024, 1);
110 mr.deallocate(p8, 1024, 8);
111 mr.deallocate(p9, 1024, 64);
112 });
113
114 return 0;
115}
116

source code of libcxx/test/std/utilities/utility/mem.res/mem.res.pool/mem.res.pool.mem/sync_deallocate_matches_allocate.pass.cpp