]> git.ipfire.org Git - thirdparty/gcc.git/blame - libstdc++-v3/testsuite/20_util/monotonic_buffer_resource/allocate.cc
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / 20_util / monotonic_buffer_resource / allocate.cc
CommitLineData
a945c346 1// Copyright (C) 2018-2024 Free Software Foundation, Inc.
dfaa3c47
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
dfaa3c47 18// { dg-do run { target c++17 } }
49ba2588 19// { dg-require-cstdint "" }
dfaa3c47
JW
20
21#include <memory_resource>
22#include <testsuite_allocator.h>
23
24void
25test01()
26{
27 __gnu_test::memory_resource r;
28
29 // test that it's possible to allocate after each of the constructors
30 {
31 std::pmr::monotonic_buffer_resource mr(&r);
32 auto p = mr.allocate(1024);
33 VERIFY( p != nullptr );
34 auto q = mr.allocate(1024);
35 VERIFY( q != nullptr );
36 VERIFY( p != q );
37 }
38 VERIFY( r.number_of_active_allocations() == 0 );
39 {
40 std::pmr::monotonic_buffer_resource mr(128, &r);
41 auto p = mr.allocate(1024);
42 VERIFY( p != nullptr );
43 auto q = mr.allocate(1024);
44 VERIFY( q != nullptr );
45 VERIFY( p != q );
46 }
47 VERIFY( r.number_of_active_allocations() == 0 );
48 {
49 unsigned char buf[64];
50 std::pmr::monotonic_buffer_resource mr((void*)buf, sizeof(buf), &r);
51 auto p = mr.allocate(1024);
52 VERIFY( p != nullptr );
53 auto q = mr.allocate(1024);
54 VERIFY( q != nullptr );
55 VERIFY( p != q );
56 }
57 VERIFY( r.number_of_active_allocations() == 0 );
58 {
59 std::pmr::monotonic_buffer_resource mr;
60 auto p = mr.allocate(1024);
61 VERIFY( p != nullptr );
62 auto q = mr.allocate(1024);
63 VERIFY( q != nullptr );
64 VERIFY( p != q );
65 }
66 {
67 std::pmr::monotonic_buffer_resource mr(64);
68 auto p = mr.allocate(1024);
69 VERIFY( p != nullptr );
70 auto q = mr.allocate(1024);
71 VERIFY( q != nullptr );
72 VERIFY( p != q );
73 }
74 {
75 unsigned char buf[64];
76 std::pmr::monotonic_buffer_resource mr((void*)buf, sizeof(buf));
77 auto p = mr.allocate(1024);
78 VERIFY( p != nullptr );
79 auto q = mr.allocate(1024);
80 VERIFY( q != nullptr );
81 VERIFY( p != q );
82 }
83}
84
85void
86test02()
87{
88 unsigned char buf[64];
89 std::pmr::monotonic_buffer_resource mr(buf, sizeof(buf));
90
91 auto p = mr.allocate(0);
92 VERIFY( p != nullptr );
93 auto q = mr.allocate(0);
94 VERIFY( q != nullptr );
95 VERIFY( p != q );
96
97 p = mr.allocate(0, 1);
98 VERIFY( p != nullptr );
99 q = mr.allocate(0, 1);
100 VERIFY( q != nullptr );
101 VERIFY( p != q );
102}
103
104void
105test03()
106{
107#if __cpp_exceptions
108 {
109 std::pmr::monotonic_buffer_resource mr(std::pmr::null_memory_resource());
110 bool caught = false;
111 try
112 {
113 (void) mr.allocate(1, 1);
114 }
115 catch (const std::bad_alloc&)
116 {
117 caught = true;
118 }
119 VERIFY( caught );
120 }
121 {
122 unsigned char buf[16];
123 std::pmr::monotonic_buffer_resource mr(buf, sizeof(buf),
124 std::pmr::null_memory_resource());
125 (void) mr.allocate(16, 1);
126 bool caught = false;
127 try
128 {
129 (void) mr.allocate(1, 1);
130 }
131 catch (const std::bad_alloc&)
132 {
133 caught = true;
134 }
135 VERIFY( caught );
136 }
137#endif
138}
139
140void
141test04()
142{
143 auto buf = new unsigned char[512];
144 std::pmr::monotonic_buffer_resource mr(buf, 512,
145 std::pmr::null_memory_resource());
146 std::size_t prev_size = 1;
147 void* prev_ptr = mr.allocate(prev_size, 1);
148 for (int i = 0; i < 9; ++i)
149 {
150 std::size_t size = 1 << i;
151 void* ptr = mr.allocate(size, 1);
13feb023 152 VERIFY( std::size_t((char*)ptr - (char*)prev_ptr) == prev_size );
dfaa3c47
JW
153 prev_ptr = ptr;
154 prev_size = size;
155 }
156}
157
158void
159test05()
160{
161 // test that returned pointer is correctly aligned
162 auto is_aligned = [](void* p, size_t alignment) -> bool {
163 return (reinterpret_cast<std::uintptr_t>(p) % alignment) == 0;
164 };
165
166 auto buf = new unsigned char[2048];
167 std::pmr::monotonic_buffer_resource mr(buf+1, 2047);
168 for (int i = 0; i < 9; ++i)
169 {
170 auto p = mr.allocate(1, 1 << i);
171 VERIFY( is_aligned(p, 1 << i) );
172 // Make next available byte misaligned:
173 (void) mr.allocate(1 << i, 1);
174 }
175}
176
177void
178test06()
179{
180 // check for geometric progression in buffer sizes from upstream
181
182 struct resource : __gnu_test::memory_resource
183 {
184 bool allocated = false;
185 std::size_t last_size = 0;
186
187 void*
188 do_allocate(size_t bytes, size_t align) override
189 {
190 allocated = true;
191 last_size = bytes;
192 return __gnu_test::memory_resource::do_allocate(bytes, align);
193 }
194 };
195
196 resource r;
197 std::pmr::monotonic_buffer_resource mr(32, &r);
198 std::size_t last_size = 0;
199
200 for (int i = 0; i < 100; ++i)
201 {
202 (void) mr.allocate(16);
203 if (r.allocated)
204 {
205 VERIFY(r.last_size >= last_size);
206 last_size = r.last_size;
207 r.allocated = false;
208 }
209 }
210}
211
1e718ec5
JW
212void
213test07()
214{
215 // Custom exception thrown on expected allocation failure.
216 struct very_bad_alloc : std::bad_alloc { };
217
218 struct careful_resource : __gnu_test::memory_resource
219 {
220 void* do_allocate(std::size_t bytes, std::size_t alignment)
221 {
222 // pmr::monotonic_buffer_resource::do_allocate is not allowed to
223 // throw an exception when asked for an allocation it can't satisfy.
224 // The libstdc++ implementation will ask upstream to allocate
225 // bytes=SIZE_MAX and alignment=bit_floor(SIZE_MAX) instead of throwing.
226 // Verify that we got those values:
227 if (bytes != std::numeric_limits<std::size_t>::max())
228 VERIFY( !"upstream allocation should request maximum number of bytes" );
229 if (alignment != (1 + std::numeric_limits<std::size_t>::max() / 2))
230 VERIFY( !"upstream allocation should request maximum alignment" );
231
232 // A successful failure:
233 throw very_bad_alloc();
234 }
235 };
236
237 careful_resource cr;
238 std::pmr::monotonic_buffer_resource mbr(&cr);
239 try
240 {
b0224734
JW
241#pragma GCC diagnostic push
242#pragma GCC diagnostic ignored "-Walloc-size-larger-than="
1e718ec5
JW
243 // Try to allocate a ridiculous size:
244 void* p = mbr.allocate(std::size_t(-2), 1);
b0224734 245#pragma GCC diagnostic pop
1e718ec5
JW
246 // Should not reach here!
247 VERIFY( !"attempt to allocate SIZE_MAX-1 should not have succeeded" );
248 throw p;
249 }
250 catch (const very_bad_alloc&)
251 {
252 // Should catch this exception from careful_resource::do_allocate
253 }
254 catch (const std::bad_alloc&)
255 {
256 VERIFY( !"monotonic_buffer_resource::do_allocate is not allowed to throw" );
257 }
258}
259
dfaa3c47
JW
260int
261main()
262{
263 test01();
264 test02();
265 test03();
266 test04();
267 test05();
268 test06();
1e718ec5 269 test07();
dfaa3c47 270}