Where Online Learning is simpler!
The C and C++ Include Header Files
/usr/include/c++/13/memory_resource
$ cat -n /usr/include/c++/13/memory_resource 1 //
-*- C++ -*- 2 3 // Copyright (C) 2018-2023 Free Software Foundation, Inc. 4 // 5 // This file is part of the GNU ISO C++ Library. This library is free 6 // software; you can redistribute it and/or modify it under the 7 // terms of the GNU General Public License as published by the 8 // Free Software Foundation; either version 3, or (at your option) 9 // any later version. 10 11 // This library is distributed in the hope that it will be useful, 12 // but WITHOUT ANY WARRANTY; without even the implied warranty of 13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 // GNU General Public License for more details. 15 16 // Under Section 7 of GPL version 3, you are granted additional 17 // permissions described in the GCC Runtime Library Exception, version 18 // 3.1, as published by the Free Software Foundation. 19 20 // You should have received a copy of the GNU General Public License and 21 // a copy of the GCC Runtime Library Exception along with this program; 22 // see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 23 //
. 24 25 /** @file include/memory_resource 26 * This is a Standard C++ Library header. 27 * 28 * This header declares the @ref pmr (std::pmr) memory resources. 29 * @ingroup pmr 30 */ 31 32 #ifndef _GLIBCXX_MEMORY_RESOURCE 33 #define _GLIBCXX_MEMORY_RESOURCE 1 34 35 #pragma GCC system_header 36 37 #include
// polymorphic allocation 38 39 #if __cplusplus >= 201703L 40 41 /** 42 * @defgroup pmr Polymorphic memory resources 43 * 44 * @anchor pmr 45 * @ingroup memory 46 * @since C++17 47 * 48 * Memory resources are classes that implement the `std::pmr::memory_resource` 49 * interface for allocating and deallocating memory. Unlike traditional C++ 50 * allocators, memory resources are not value types and are used via pointers 51 * to the abstract base class. They are only responsible for allocating and 52 * deallocating, not for construction and destruction of objects. As a result, 53 * memory resources just allocate raw memory as type `void*` and are not 54 * templates that allocate/deallocate and construct/destroy a specific type. 55 * 56 * The class template `std::pmr::polymorphic_allocator` is an allocator that 57 * uses a memory resource for its allocations. 58 */ 59 60 #include
61 #include
// vector 62 #include
// shared_mutex 63 #include
// align 64 #include
65 66 namespace std _GLIBCXX_VISIBILITY(default) 67 { 68 _GLIBCXX_BEGIN_NAMESPACE_VERSION 69 namespace pmr 70 { 71 #ifdef _GLIBCXX_HAS_GTHREADS 72 // Header and all contents are present. 73 # define __cpp_lib_memory_resource 201603L 74 #else 75 // The pmr::synchronized_pool_resource type is missing. 76 # define __cpp_lib_memory_resource 1 77 #endif 78 79 #if __cplusplus >= 202002L 80 # define __cpp_lib_polymorphic_allocator 201902L 81 template
82 class polymorphic_allocator; 83 #endif 84 85 // Global memory resources 86 87 /// A pmr::memory_resource that uses `new` to allocate memory 88 /** 89 * @ingroup pmr 90 * @headerfile memory_resource 91 * @since C++17 92 */ 93 [[nodiscard, __gnu__::__returns_nonnull__, __gnu__::__const__]] 94 memory_resource* 95 new_delete_resource() noexcept; 96 97 /// A pmr::memory_resource that always throws `bad_alloc` 98 [[nodiscard, __gnu__::__returns_nonnull__, __gnu__::__const__]] 99 memory_resource* 100 null_memory_resource() noexcept; 101 102 /// Replace the default memory resource pointer 103 [[__gnu__::__returns_nonnull__]] 104 memory_resource* 105 set_default_resource(memory_resource* __r) noexcept; 106 107 /// Get the current default memory resource pointer 108 [[__gnu__::__returns_nonnull__]] 109 memory_resource* 110 get_default_resource() noexcept; 111 112 // Pool resource classes 113 struct pool_options; 114 #ifdef _GLIBCXX_HAS_GTHREADS 115 class synchronized_pool_resource; 116 #endif 117 class unsynchronized_pool_resource; 118 class monotonic_buffer_resource; 119 120 /// Parameters for tuning a pool resource's behaviour. 121 /** 122 * @ingroup pmr 123 * @headerfile memory_resource 124 * @since C++17 125 */ 126 struct pool_options 127 { 128 /** @brief Upper limit on number of blocks in a chunk. 129 * 130 * A lower value prevents allocating huge chunks that could remain mostly 131 * unused, but means pools will need to replenished more frequently. 132 */ 133 size_t max_blocks_per_chunk = 0; 134 135 /* @brief Largest block size (in bytes) that should be served from pools. 136 * 137 * Larger allocations will be served directly by the upstream resource, 138 * not from one of the pools managed by the pool resource. 139 */ 140 size_t largest_required_pool_block = 0; 141 }; 142 143 // Common implementation details for un-/synchronized pool resources. 144 class __pool_resource 145 { 146 friend class synchronized_pool_resource; 147 friend class unsynchronized_pool_resource; 148 149 __pool_resource(const pool_options& __opts, memory_resource* __upstream); 150 151 ~__pool_resource(); 152 153 __pool_resource(const __pool_resource&) = delete; 154 __pool_resource& operator=(const __pool_resource&) = delete; 155 156 // Allocate a large unpooled block. 157 void* 158 allocate(size_t __bytes, size_t __alignment); 159 160 // Deallocate a large unpooled block. 161 void 162 deallocate(void* __p, size_t __bytes, size_t __alignment); 163 164 165 // Deallocate unpooled memory. 166 void release() noexcept; 167 168 memory_resource* resource() const noexcept 169 { return _M_unpooled.get_allocator().resource(); } 170 171 struct _Pool; 172 173 _Pool* _M_alloc_pools(); 174 175 const pool_options _M_opts; 176 177 struct _BigBlock; 178 // Collection of blocks too big for any pool, sorted by address. 179 // This also stores the only copy of the upstream memory resource pointer. 180 _GLIBCXX_STD_C::pmr::vector<_BigBlock> _M_unpooled; 181 182 const int _M_npools; 183 }; 184 185 #ifdef _GLIBCXX_HAS_GTHREADS 186 /// A thread-safe memory resource that manages pools of fixed-size blocks. 187 /** 188 * @ingroup pmr 189 * @headerfile memory_resource 190 * @since C++17 191 */ 192 class synchronized_pool_resource : public memory_resource 193 { 194 public: 195 synchronized_pool_resource(const pool_options& __opts, 196 memory_resource* __upstream) 197 __attribute__((__nonnull__)); 198 199 synchronized_pool_resource() 200 : synchronized_pool_resource(pool_options(), get_default_resource()) 201 { } 202 203 explicit 204 synchronized_pool_resource(memory_resource* __upstream) 205 __attribute__((__nonnull__)) 206 : synchronized_pool_resource(pool_options(), __upstream) 207 { } 208 209 explicit 210 synchronized_pool_resource(const pool_options& __opts) 211 : synchronized_pool_resource(__opts, get_default_resource()) { } 212 213 synchronized_pool_resource(const synchronized_pool_resource&) = delete; 214 215 virtual ~synchronized_pool_resource(); 216 217 synchronized_pool_resource& 218 operator=(const synchronized_pool_resource&) = delete; 219 220 void release(); 221 222 memory_resource* 223 upstream_resource() const noexcept 224 __attribute__((__returns_nonnull__)) 225 { return _M_impl.resource(); } 226 227 pool_options options() const noexcept { return _M_impl._M_opts; } 228 229 protected: 230 void* 231 do_allocate(size_t __bytes, size_t __alignment) override; 232 233 void 234 do_deallocate(void* __p, size_t __bytes, size_t __alignment) override; 235 236 bool 237 do_is_equal(const memory_resource& __other) const noexcept override 238 { return this == &__other; } 239 240 public: 241 // Thread-specific pools (only public for access by implementation details) 242 struct _TPools; 243 244 private: 245 _TPools* _M_alloc_tpools(lock_guard
&); 246 _TPools* _M_alloc_shared_tpools(lock_guard
&); 247 auto _M_thread_specific_pools() noexcept; 248 249 __pool_resource _M_impl; 250 __gthread_key_t _M_key; 251 // Linked list of thread-specific pools. All threads share _M_tpools[0]. 252 _TPools* _M_tpools = nullptr; 253 mutable shared_mutex _M_mx; 254 }; 255 #endif 256 257 /// A non-thread-safe memory resource that manages pools of fixed-size blocks. 258 /** 259 * @ingroup pmr 260 * @headerfile memory_resource 261 * @since C++17 262 */ 263 class unsynchronized_pool_resource : public memory_resource 264 { 265 public: 266 [[__gnu__::__nonnull__]] 267 unsynchronized_pool_resource(const pool_options& __opts, 268 memory_resource* __upstream); 269 270 unsynchronized_pool_resource() 271 : unsynchronized_pool_resource(pool_options(), get_default_resource()) 272 { } 273 274 [[__gnu__::__nonnull__]] 275 explicit 276 unsynchronized_pool_resource(memory_resource* __upstream) 277 : unsynchronized_pool_resource(pool_options(), __upstream) 278 { } 279 280 explicit 281 unsynchronized_pool_resource(const pool_options& __opts) 282 : unsynchronized_pool_resource(__opts, get_default_resource()) { } 283 284 unsynchronized_pool_resource(const unsynchronized_pool_resource&) = delete; 285 286 virtual ~unsynchronized_pool_resource(); 287 288 unsynchronized_pool_resource& 289 operator=(const unsynchronized_pool_resource&) = delete; 290 291 void release(); 292 293 [[__gnu__::__returns_nonnull__]] 294 memory_resource* 295 upstream_resource() const noexcept 296 { return _M_impl.resource(); } 297 298 pool_options options() const noexcept { return _M_impl._M_opts; } 299 300 protected: 301 void* 302 do_allocate(size_t __bytes, size_t __alignment) override; 303 304 void 305 do_deallocate(void* __p, size_t __bytes, size_t __alignment) override; 306 307 bool 308 do_is_equal(const memory_resource& __other) const noexcept override 309 { return this == &__other; } 310 311 private: 312 using _Pool = __pool_resource::_Pool; 313 314 auto _M_find_pool(size_t) noexcept; 315 316 __pool_resource _M_impl; 317 _Pool* _M_pools = nullptr; 318 }; 319 320 /// A memory resource that allocates from a fixed-size buffer. 321 /** 322 * The main feature of a `pmr::monotonic_buffer_resource` is that its 323 * `do_deallocate` does nothing. This makes it very fast because there is no 324 * need to manage a free list, and every allocation simply returns a new 325 * block of memory, rather than searching for a suitably-sized free block. 326 * Because deallocating is a no-op, the amount of memory used by the resource 327 * only grows until `release()` (or the destructor) is called to return all 328 * memory to upstream. 329 * 330 * A `monotonic_buffer_resource` can be initialized with a buffer that 331 * will be used to satisfy all allocation requests, until the buffer is full. 332 * After that a new buffer will be allocated from the upstream resource. 333 * By using a stack buffer and `pmr::null_memory_resource()` as the upstream 334 * you can get a memory resource that only uses the stack and never 335 * dynamically allocates. 336 * 337 * @ingroup pmr 338 * @headerfile memory_resource 339 * @since C++17 340 */ 341 class monotonic_buffer_resource : public memory_resource 342 { 343 public: 344 explicit 345 monotonic_buffer_resource(memory_resource* __upstream) noexcept 346 __attribute__((__nonnull__)) 347 : _M_upstream(__upstream) 348 { _GLIBCXX_DEBUG_ASSERT(__upstream != nullptr); } 349 350 monotonic_buffer_resource(size_t __initial_size, 351 memory_resource* __upstream) noexcept 352 __attribute__((__nonnull__)) 353 : _M_next_bufsiz(__initial_size), 354 _M_upstream(__upstream) 355 { 356 _GLIBCXX_DEBUG_ASSERT(__upstream != nullptr); 357 _GLIBCXX_DEBUG_ASSERT(__initial_size > 0); 358 } 359 360 monotonic_buffer_resource(void* __buffer, size_t __buffer_size, 361 memory_resource* __upstream) noexcept 362 __attribute__((__nonnull__(4))) 363 : _M_current_buf(__buffer), _M_avail(__buffer_size), 364 _M_next_bufsiz(_S_next_bufsize(__buffer_size)), 365 _M_upstream(__upstream), 366 _M_orig_buf(__buffer), _M_orig_size(__buffer_size) 367 { 368 _GLIBCXX_DEBUG_ASSERT(__upstream != nullptr); 369 _GLIBCXX_DEBUG_ASSERT(__buffer != nullptr || __buffer_size == 0); 370 } 371 372 monotonic_buffer_resource() noexcept 373 : monotonic_buffer_resource(get_default_resource()) 374 { } 375 376 explicit 377 monotonic_buffer_resource(size_t __initial_size) noexcept 378 : monotonic_buffer_resource(__initial_size, get_default_resource()) 379 { } 380 381 monotonic_buffer_resource(void* __buffer, size_t __buffer_size) noexcept 382 : monotonic_buffer_resource(__buffer, __buffer_size, get_default_resource()) 383 { } 384 385 monotonic_buffer_resource(const monotonic_buffer_resource&) = delete; 386 387 virtual ~monotonic_buffer_resource(); // key function 388 389 monotonic_buffer_resource& 390 operator=(const monotonic_buffer_resource&) = delete; 391 392 void 393 release() noexcept 394 { 395 if (_M_head) 396 _M_release_buffers(); 397 398 // reset to initial state at contruction: 399 if ((_M_current_buf = _M_orig_buf)) 400 { 401 _M_avail = _M_orig_size; 402 _M_next_bufsiz = _S_next_bufsize(_M_orig_size); 403 } 404 else 405 { 406 _M_avail = 0; 407 _M_next_bufsiz = _M_orig_size; 408 } 409 } 410 411 memory_resource* 412 upstream_resource() const noexcept 413 __attribute__((__returns_nonnull__)) 414 { return _M_upstream; } 415 416 protected: 417 void* 418 do_allocate(size_t __bytes, size_t __alignment) override 419 { 420 if (__builtin_expect(__bytes == 0, false)) 421 __bytes = 1; // Ensures we don't return the same pointer twice. 422 423 void* __p = std::align(__alignment, __bytes, _M_current_buf, _M_avail); 424 if (__builtin_expect(__p == nullptr, false)) 425 { 426 _M_new_buffer(__bytes, __alignment); 427 __p = _M_current_buf; 428 } 429 _M_current_buf = (char*)_M_current_buf + __bytes; 430 _M_avail -= __bytes; 431 return __p; 432 } 433 434 void 435 do_deallocate(void*, size_t, size_t) override 436 { } 437 438 bool 439 do_is_equal(const memory_resource& __other) const noexcept override 440 { return this == &__other; } 441 442 private: 443 // Update _M_current_buf and _M_avail to refer to a new buffer with 444 // at least the specified size and alignment, allocated from upstream. 445 void 446 _M_new_buffer(size_t __bytes, size_t __alignment); 447 448 // Deallocate all buffers obtained from upstream. 449 void 450 _M_release_buffers() noexcept; 451 452 static size_t 453 _S_next_bufsize(size_t __buffer_size) noexcept 454 { 455 if (__builtin_expect(__buffer_size == 0, false)) 456 __buffer_size = 1; 457 return __buffer_size * _S_growth_factor; 458 } 459 460 static constexpr size_t _S_init_bufsize = 128 * sizeof(void*); 461 static constexpr float _S_growth_factor = 1.5; 462 463 void* _M_current_buf = nullptr; 464 size_t _M_avail = 0; 465 size_t _M_next_bufsiz = _S_init_bufsize; 466 467 // Initial values set at construction and reused by release(): 468 memory_resource* const _M_upstream; 469 void* const _M_orig_buf = nullptr; 470 size_t const _M_orig_size = _M_next_bufsiz; 471 472 class _Chunk; 473 _Chunk* _M_head = nullptr; 474 }; 475 476 } // namespace pmr 477 _GLIBCXX_END_NAMESPACE_VERSION 478 } // namespace std 479 480 #endif // C++17 481 #endif // _GLIBCXX_MEMORY_RESOURCE
Contact us
|
About us
|
Term of use
|
Copyright © 2000-2025 MyWebUniversity.com ™