1 // Copyright (C) 2018-2024 Free Software Foundation, Inc.
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)
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.
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/>.
18 // { dg-do run { target c++17 } }
19 // { dg-additional-options "-pthread" { target pthread } }
20 // { dg-require-gthreads "" }
22 #include <memory_resource>
24 #include <testsuite_allocator.h>
25 #include <testsuite_hooks.h>
30 __gnu_test::memory_resource test_mr
;
32 std::pmr::synchronized_pool_resource
r(&test_mr
);
33 void* p1
= r
.allocate(1, 1);
34 VERIFY( p1
!= nullptr );
35 auto n
= test_mr
.number_of_active_allocations();
37 // Ensure memory region can be written to (without corrupting heap!)
38 std::memset(p1
, 0xff, 1);
39 void* p2
= r
.allocate(1, 1);
40 VERIFY( p2
!= nullptr );
42 VERIFY( test_mr
.number_of_active_allocations() == n
);
43 std::memset(p1
, 0xff, 1);
44 r
.deallocate(p1
, 1, 1);
45 // Returning single blocks to the pool doesn't return them upstream:
46 VERIFY( test_mr
.number_of_active_allocations() == n
);
47 r
.deallocate(p2
, 1, 1);
48 VERIFY( test_mr
.number_of_active_allocations() == n
);
50 VERIFY( test_mr
.number_of_active_allocations() == 0 );
56 struct nullable_memory_resource
: public std::pmr::memory_resource
59 do_allocate(std::size_t bytes
, std::size_t alignment
) override
60 { return upstream
->allocate(bytes
, alignment
); }
63 do_deallocate(void* p
, std::size_t bytes
, std::size_t alignment
) override
64 { upstream
->deallocate(p
, bytes
, alignment
); }
67 do_is_equal(const memory_resource
& r
) const noexcept override
68 { return &r
== this; }
70 std::pmr::memory_resource
* upstream
= std::pmr::get_default_resource();
73 nullable_memory_resource test_mr
;
74 std::pmr::synchronized_pool_resource
r(&test_mr
);
75 void* p1
= r
.allocate(8, 1);
76 VERIFY( p1
!= nullptr );
77 std::memset(p1
, 0xff, 8);
78 test_mr
.upstream
= nullptr;
79 void* p2
= r
.allocate(8, 1); //should not need to replenish
80 VERIFY( p2
!= nullptr );
82 std::memset(p1
, 0xff, 8);
83 r
.deallocate(p1
, 8, 1); // should not use upstream
84 r
.deallocate(p2
, 8, 1); // should not use upstream
86 // Destructor will return memory upstream, so restore the upstream resource:
87 test_mr
.upstream
= std::pmr::get_default_resource();
93 __gnu_test::memory_resource test_mr
;
95 std::pmr::synchronized_pool_resource
r({10, 16}, &test_mr
);
96 std::size_t largest_pool
= r
.options().largest_required_pool_block
;
97 void* p1
= r
.allocate(2 * largest_pool
);
98 VERIFY( p1
!= nullptr );
99 const std::size_t n
= test_mr
.number_of_active_allocations();
100 // Allocation of pools + allocation of pmr::vector + oversize allocation:
102 std::memset(p1
, 0xff, 2 * largest_pool
);
103 void* p2
= r
.allocate(3 * largest_pool
);
104 VERIFY( p2
!= nullptr );
106 VERIFY( test_mr
.number_of_active_allocations() == n
+ 1 );
107 std::memset(p2
, 0xff, 3 * largest_pool
);
108 r
.deallocate(p1
, 2 * largest_pool
);
109 VERIFY( test_mr
.number_of_active_allocations() == n
);
110 r
.deallocate(p2
, 3 * largest_pool
);
111 VERIFY( test_mr
.number_of_active_allocations() == n
- 1 );
113 VERIFY( test_mr
.number_of_active_allocations() == 0 );
115 std::pmr::synchronized_pool_resource
r({16, 16}, &test_mr
);
116 (void) r
.allocate(2);
117 (void) r
.allocate(8);
118 (void) r
.allocate(16);
119 (void) r
.allocate(2);
120 (void) r
.allocate(8);
121 (void) r
.allocate(16);
122 (void) r
.allocate(2 * r
.options().largest_required_pool_block
);
123 VERIFY( test_mr
.number_of_active_allocations() != 0 );
124 // Destructor calls release()
126 VERIFY( test_mr
.number_of_active_allocations() == 0 );
132 __gnu_test::memory_resource test_mr
;
133 std::pmr::synchronized_pool_resource
r({256, 256}, &test_mr
);
135 void* p1
= r
.allocate(2, 64);
136 VERIFY( (std::uintptr_t)p1
% 64 == 0 );
137 void* p2
= r
.allocate(2, 128);
138 VERIFY( (std::uintptr_t)p2
% 128 == 0 );
139 void* p3
= r
.allocate(2, 256);
140 VERIFY( (std::uintptr_t)p3
% 256 == 0 );
141 const std::size_t largest_pool
= r
.options().largest_required_pool_block
;
142 void* p4
= r
.allocate(2 * largest_pool
, 1024);
143 VERIFY( (std::uintptr_t)p4
% 1024 == 0 );
144 r
.deallocate(p1
, 2, 64);
145 r
.deallocate(p2
, 2, 128);
146 r
.deallocate(p3
, 2, 256);
147 r
.deallocate(p4
, 2 * largest_pool
, 1024);