]> git.ipfire.org Git - thirdparty/gcc.git/blob - libstdc++-v3/testsuite/20_util/synchronized_pool_resource/allocate.cc
Update copyright years.
[thirdparty/gcc.git] / libstdc++-v3 / testsuite / 20_util / synchronized_pool_resource / allocate.cc
1 // Copyright (C) 2018-2024 Free Software Foundation, Inc.
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 { target c++17 } }
19 // { dg-additional-options "-pthread" { target pthread } }
20 // { dg-require-gthreads "" }
21
22 #include <memory_resource>
23 #include <cstring>
24 #include <testsuite_allocator.h>
25 #include <testsuite_hooks.h>
26
27 void
28 test01()
29 {
30 __gnu_test::memory_resource test_mr;
31 {
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();
36 VERIFY( n > 0 );
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 );
41 VERIFY( p2 != p1 );
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 );
49 }
50 VERIFY( test_mr.number_of_active_allocations() == 0 );
51 }
52
53 void
54 test02()
55 {
56 struct nullable_memory_resource : public std::pmr::memory_resource
57 {
58 void*
59 do_allocate(std::size_t bytes, std::size_t alignment) override
60 { return upstream->allocate(bytes, alignment); }
61
62 void
63 do_deallocate(void* p, std::size_t bytes, std::size_t alignment) override
64 { upstream->deallocate(p, bytes, alignment); }
65
66 bool
67 do_is_equal(const memory_resource& r) const noexcept override
68 { return &r == this; }
69
70 std::pmr::memory_resource* upstream = std::pmr::get_default_resource();
71 };
72
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 );
81 VERIFY( p2 != p1 );
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
85
86 // Destructor will return memory upstream, so restore the upstream resource:
87 test_mr.upstream = std::pmr::get_default_resource();
88 }
89
90 void
91 test03()
92 {
93 __gnu_test::memory_resource test_mr;
94 {
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:
101 VERIFY( n >= 1 );
102 std::memset(p1, 0xff, 2 * largest_pool);
103 void* p2 = r.allocate(3 * largest_pool);
104 VERIFY( p2 != nullptr );
105 VERIFY( p2 != p1 );
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 );
112 }
113 VERIFY( test_mr.number_of_active_allocations() == 0 );
114 {
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()
125 }
126 VERIFY( test_mr.number_of_active_allocations() == 0 );
127 }
128
129 void
130 test04()
131 {
132 __gnu_test::memory_resource test_mr;
133 std::pmr::synchronized_pool_resource r({256, 256}, &test_mr);
134 // Check alignment
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);
148 }
149
150 int
151 main()
152 {
153 test01();
154 test02();
155 test03();
156 test04();
157 }