]>
Commit | Line | Data |
---|---|---|
99dee823 | 1 | // Copyright (C) 2018-2021 Free Software Foundation, Inc. |
c5be6481 JW |
2 | // |
3 | // This file is part of the GNU ISO C++ Library. This library is free | |
4 | // software; you can redistribute it and/or modify it under the | |
5 | // terms of the GNU General Public License as published by the | |
6 | // Free Software Foundation; either version 3, or (at your option) | |
7 | // any later version. | |
8 | ||
9 | // This library is distributed in the hope that it will be useful, | |
10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | // GNU General Public License for more details. | |
13 | ||
14 | // You should have received a copy of the GNU General Public License along | |
15 | // with this library; see the file COPYING3. If not see | |
16 | // <http://www.gnu.org/licenses/>. | |
17 | ||
18 | // { dg-do run } | |
19 | // { dg-options "-std=gnu++17 -pthread" } | |
20 | // { dg-require-effective-target c++17 } | |
21 | // { dg-require-effective-target pthread } | |
22 | // { dg-require-gthreads "" } | |
23 | ||
24 | #include <memory_resource> | |
25 | #include <cstring> | |
26 | #include <testsuite_allocator.h> | |
27 | #include <testsuite_hooks.h> | |
28 | ||
29 | void | |
30 | test01() | |
31 | { | |
32 | __gnu_test::memory_resource test_mr; | |
33 | { | |
34 | std::pmr::synchronized_pool_resource r(&test_mr); | |
35 | void* p1 = r.allocate(1, 1); | |
36 | VERIFY( p1 != nullptr ); | |
37 | auto n = test_mr.number_of_active_allocations(); | |
38 | VERIFY( n > 0 ); | |
39 | // Ensure memory region can be written to (without corrupting heap!) | |
40 | std::memset(p1, 0xff, 1); | |
41 | void* p2 = r.allocate(1, 1); | |
42 | VERIFY( p2 != nullptr ); | |
43 | VERIFY( p2 != p1 ); | |
44 | VERIFY( test_mr.number_of_active_allocations() == n ); | |
45 | std::memset(p1, 0xff, 1); | |
46 | r.deallocate(p1, 1, 1); | |
47 | // Returning single blocks to the pool doesn't return them upstream: | |
48 | VERIFY( test_mr.number_of_active_allocations() == n ); | |
49 | r.deallocate(p2, 1, 1); | |
50 | VERIFY( test_mr.number_of_active_allocations() == n ); | |
51 | } | |
52 | VERIFY( test_mr.number_of_active_allocations() == 0 ); | |
53 | } | |
54 | ||
55 | void | |
56 | test02() | |
57 | { | |
58 | struct nullable_memory_resource : public std::pmr::memory_resource | |
59 | { | |
60 | void* | |
61 | do_allocate(std::size_t bytes, std::size_t alignment) override | |
62 | { return upstream->allocate(bytes, alignment); } | |
63 | ||
64 | void | |
65 | do_deallocate(void* p, std::size_t bytes, std::size_t alignment) override | |
66 | { upstream->deallocate(p, bytes, alignment); } | |
67 | ||
68 | bool | |
69 | do_is_equal(const memory_resource& r) const noexcept override | |
70 | { return &r == this; } | |
71 | ||
72 | std::pmr::memory_resource* upstream = std::pmr::get_default_resource(); | |
73 | }; | |
74 | ||
75 | nullable_memory_resource test_mr; | |
76 | std::pmr::synchronized_pool_resource r(&test_mr); | |
77 | void* p1 = r.allocate(8, 1); | |
78 | VERIFY( p1 != nullptr ); | |
79 | std::memset(p1, 0xff, 8); | |
80 | test_mr.upstream = nullptr; | |
81 | void* p2 = r.allocate(8, 1); //should not need to replenish | |
82 | VERIFY( p2 != nullptr ); | |
83 | VERIFY( p2 != p1 ); | |
84 | std::memset(p1, 0xff, 8); | |
85 | r.deallocate(p1, 8, 1); // should not use upstream | |
86 | r.deallocate(p2, 8, 1); // should not use upstream | |
87 | ||
88 | // Destructor will return memory upstream, so restore the upstream resource: | |
89 | test_mr.upstream = std::pmr::get_default_resource(); | |
90 | } | |
91 | ||
92 | void | |
93 | test03() | |
94 | { | |
95 | __gnu_test::memory_resource test_mr; | |
96 | { | |
97 | std::pmr::synchronized_pool_resource r({10, 16}, &test_mr); | |
98 | std::size_t largest_pool = r.options().largest_required_pool_block; | |
99 | void* p1 = r.allocate(2 * largest_pool); | |
100 | VERIFY( p1 != nullptr ); | |
101 | const std::size_t n = test_mr.number_of_active_allocations(); | |
102 | // Allocation of pools + allocation of pmr::vector + oversize allocation: | |
103 | VERIFY( n >= 1 ); | |
104 | std::memset(p1, 0xff, 2 * largest_pool); | |
105 | void* p2 = r.allocate(3 * largest_pool); | |
106 | VERIFY( p2 != nullptr ); | |
107 | VERIFY( p2 != p1 ); | |
108 | VERIFY( test_mr.number_of_active_allocations() == n + 1 ); | |
109 | std::memset(p2, 0xff, 3 * largest_pool); | |
110 | r.deallocate(p1, 2 * largest_pool); | |
111 | VERIFY( test_mr.number_of_active_allocations() == n ); | |
112 | r.deallocate(p2, 3 * largest_pool); | |
113 | VERIFY( test_mr.number_of_active_allocations() == n - 1 ); | |
114 | } | |
115 | VERIFY( test_mr.number_of_active_allocations() == 0 ); | |
116 | { | |
117 | std::pmr::synchronized_pool_resource r({16, 16}, &test_mr); | |
118 | (void) r.allocate(2); | |
119 | (void) r.allocate(8); | |
120 | (void) r.allocate(16); | |
121 | (void) r.allocate(2); | |
122 | (void) r.allocate(8); | |
123 | (void) r.allocate(16); | |
124 | (void) r.allocate(2 * r.options().largest_required_pool_block); | |
125 | VERIFY( test_mr.number_of_active_allocations() != 0 ); | |
126 | // Destructor calls release() | |
127 | } | |
128 | VERIFY( test_mr.number_of_active_allocations() == 0 ); | |
129 | } | |
130 | ||
131 | void | |
132 | test04() | |
133 | { | |
134 | __gnu_test::memory_resource test_mr; | |
135 | std::pmr::synchronized_pool_resource r({256, 256}, &test_mr); | |
136 | // Check alignment | |
137 | void* p1 = r.allocate(2, 64); | |
138 | VERIFY( (std::uintptr_t)p1 % 64 == 0 ); | |
139 | void* p2 = r.allocate(2, 128); | |
140 | VERIFY( (std::uintptr_t)p2 % 128 == 0 ); | |
141 | void* p3 = r.allocate(2, 256); | |
142 | VERIFY( (std::uintptr_t)p3 % 256 == 0 ); | |
143 | const std::size_t largest_pool = r.options().largest_required_pool_block; | |
144 | void* p4 = r.allocate(2 * largest_pool, 1024); | |
145 | VERIFY( (std::uintptr_t)p4 % 1024 == 0 ); | |
146 | r.deallocate(p1, 2, 64); | |
147 | r.deallocate(p2, 2, 128); | |
148 | r.deallocate(p3, 2, 256); | |
149 | r.deallocate(p4, 2 * largest_pool, 1024); | |
150 | } | |
151 | ||
152 | int | |
153 | main() | |
154 | { | |
155 | test01(); | |
156 | test02(); | |
157 | test03(); | |
158 | test04(); | |
159 | } |