[mem.res] # 20 Memory management library [[mem]](./#mem) ## 20.5 Memory resources [mem.res] ### [20.5.1](#syn) Header synopsis [[mem.res.syn]](mem.res.syn) [🔗](#header:%3cmemory_resource%3e) namespace std::pmr {// [[mem.res.class]](#class "20.5.2 Class memory_­resource"), class memory_resourceclass memory_resource; bool operator==(const memory_resource& a, const memory_resource& b) noexcept; // [[mem.poly.allocator.class]](#mem.poly.allocator.class "20.5.3 Class template polymorphic_­allocator"), class template polymorphic_allocatortemplate class polymorphic_allocator; templatebool operator==(const polymorphic_allocator& a, const polymorphic_allocator& b) noexcept; // [[mem.res.global]](#global "20.5.4 Access to program-wide memory_­resource objects"), global memory resources memory_resource* new_delete_resource() noexcept; memory_resource* null_memory_resource() noexcept; memory_resource* set_default_resource(memory_resource* r) noexcept; memory_resource* get_default_resource() noexcept; // [[mem.res.pool]](#pool "20.5.5 Pool resource classes"), pool resource classesstruct pool_options; class synchronized_pool_resource; class unsynchronized_pool_resource; class monotonic_buffer_resource;} ### [20.5.2](#class) Class memory_resource [[mem.res.class]](mem.res.class) #### [20.5.2.1](#class.general) General [[mem.res.class.general]](mem.res.class.general) [1](#class.general-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7484) The memory_resource class is an abstract interface to an unbounded set of classes encapsulating memory resources[.](#class.general-1.sentence-1) [🔗](#lib:memory_resource) namespace std::pmr {class memory_resource {static constexpr size_t max_align = alignof(max_align_t); // *exposition only*public: memory_resource() = default; memory_resource(const memory_resource&) = default; virtual ~memory_resource(); memory_resource& operator=(const memory_resource&) = default; void* allocate(size_t bytes, size_t alignment = max_align); void deallocate(void* p, size_t bytes, size_t alignment = max_align); bool is_equal(const memory_resource& other) const noexcept; private:virtual void* do_allocate(size_t bytes, size_t alignment) = 0; virtual void do_deallocate(void* p, size_t bytes, size_t alignment) = 0; virtual bool do_is_equal(const memory_resource& other) const noexcept = 0; };} #### [20.5.2.2](#public) Public member functions [[mem.res.public]](mem.res.public) [🔗](#lib:memory_resource,destructor) `~memory_resource(); ` [1](#public-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7524) *Effects*: Destroys this memory_resource[.](#public-1.sentence-1) [🔗](#lib:allocate,memory_resource) `void* allocate(size_t bytes, size_t alignment = max_align); ` [2](#public-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7535) *Effects*: Allocates storage by calling do_allocate(bytes, alignment) and implicitly creates objects within the allocated region of storage[.](#public-2.sentence-1) [3](#public-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7540) *Returns*: A pointer to a suitable created object ([[intro.object]](intro.object "6.8.2 Object model")) in the allocated region of storage[.](#public-3.sentence-1) [4](#public-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7545) *Throws*: What and when the call to do_allocate throws[.](#public-4.sentence-1) [🔗](#lib:deallocate,memory_resource) `void deallocate(void* p, size_t bytes, size_t alignment = max_align); ` [5](#public-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7556) *Effects*: Equivalent to do_deallocate(p, bytes, alignment)[.](#public-5.sentence-1) [🔗](#lib:is_equal,memory_resource) `bool is_equal(const memory_resource& other) const noexcept; ` [6](#public-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7567) *Effects*: Equivalent to: return do_is_equal(other); #### [20.5.2.3](#private) Private virtual member functions [[mem.res.private]](mem.res.private) [🔗](#lib:do_allocate,memory_resource) `virtual void* do_allocate(size_t bytes, size_t alignment) = 0; ` [1](#private-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7581) *Preconditions*: alignment is a power of two[.](#private-1.sentence-1) [2](#private-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7585) *Returns*: A derived class shall implement this function to return a pointer to allocated storage ([[basic.stc.dynamic.allocation]](basic.stc.dynamic.allocation "6.8.6.5.2 Allocation functions")) with a size of at least bytes, aligned to the specified alignment[.](#private-2.sentence-1) [3](#private-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7592) *Throws*: A derived class implementation shall throw an appropriate exception if it is unable to allocate memory with the requested size and alignment[.](#private-3.sentence-1) [🔗](#lib:do_deallocate,memory_resource) `virtual void do_deallocate(void* p, size_t bytes, size_t alignment) = 0; ` [4](#private-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7603) *Preconditions*: p was returned from a prior call to allocate(bytes, alignment) on a memory resource equal to *this, and the storage at p has not yet been deallocated[.](#private-4.sentence-1) [5](#private-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7609) *Effects*: A derived class shall implement this function to dispose of allocated storage[.](#private-5.sentence-1) [6](#private-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7613) *Throws*: Nothing[.](#private-6.sentence-1) [🔗](#lib:do_is_equal,memory_resource) `virtual bool do_is_equal(const memory_resource& other) const noexcept = 0; ` [7](#private-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7624) *Returns*: A derived class shall implement this function to return true if memory allocated from *this can be deallocated from other and vice-versa, otherwise false[.](#private-7.sentence-1) [*Note [1](#private-note-1)*: It is possible that the most-derived type of other does not match the type of *this[.](#private-7.sentence-2) For a derived class D, an implementation of this function can immediately return false if dynamic_cast(&other) == nullptr[.](#private-7.sentence-3) — *end note*] #### [20.5.2.4](#eq) Equality [[mem.res.eq]](mem.res.eq) [🔗](#lib:operator==,memory_resource) `bool operator==(const memory_resource& a, const memory_resource& b) noexcept; ` [1](#eq-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7644) *Returns*: &a == &b || a.is_equal(b)[.](#eq-1.sentence-1) ### [20.5.3](#mem.poly.allocator.class) Class template polymorphic_allocator [[mem.poly.allocator.class]](mem.poly.allocator.class) #### [20.5.3.1](#mem.poly.allocator.class.general) General [[mem.poly.allocator.class.general]](mem.poly.allocator.class.general) [1](#mem.poly.allocator.class.general-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7653) A specialization of class template pmr​::​polymorphic_allocator meets the *Cpp17Allocator* requirements ([[allocator.requirements.general]](allocator.requirements.general "16.4.4.6.1 General")) if its template argument is a cv-unqualified object type[.](#mem.poly.allocator.class.general-1.sentence-1) Constructed with different memory resources, different instances of the same specialization of pmr​::​polymorphic_allocator can exhibit entirely different allocation behavior[.](#mem.poly.allocator.class.general-1.sentence-2) This runtime polymorphism allows objects that use polymorphic_allocator to behave as if they used different allocator types at run time even though they use the same static allocator type[.](#mem.poly.allocator.class.general-1.sentence-3) [2](#mem.poly.allocator.class.general-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7664) A specialization of class template pmr​::​polymorphic_allocator meets the allocator completeness requirements ([[allocator.requirements.completeness]](allocator.requirements.completeness "16.4.4.6.2 Allocator completeness requirements")) if its template argument is a cv-unqualified object type[.](#mem.poly.allocator.class.general-2.sentence-1) [🔗](#lib:polymorphic_allocator) namespace std::pmr {template class polymorphic_allocator { memory_resource* memory_rsrc; // *exposition only*public:using value_type = Tp; // [[mem.poly.allocator.ctor]](#mem.poly.allocator.ctor "20.5.3.2 Constructors"), constructors polymorphic_allocator() noexcept; polymorphic_allocator(memory_resource* r); polymorphic_allocator(const polymorphic_allocator& other) = default; template polymorphic_allocator(const polymorphic_allocator& other) noexcept; polymorphic_allocator& operator=(const polymorphic_allocator&) = delete; // [[mem.poly.allocator.mem]](#mem.poly.allocator.mem "20.5.3.3 Member functions"), member functions Tp* allocate(size_t n); void deallocate(Tp* p, size_t n); void* allocate_bytes(size_t nbytes, size_t alignment = alignof(max_align_t)); void deallocate_bytes(void* p, size_t nbytes, size_t alignment = alignof(max_align_t)); template T* allocate_object(size_t n = 1); template void deallocate_object(T* p, size_t n = 1); template T* new_object(CtorArgs&&... ctor_args); template void delete_object(T* p); templatevoid construct(T* p, Args&&... args); templatevoid destroy(T* p); polymorphic_allocator select_on_container_copy_construction() const; memory_resource* resource() const; // friendsfriend bool operator==(const polymorphic_allocator& a, const polymorphic_allocator& b) noexcept {return *a.resource() == *b.resource(); }};} #### [20.5.3.2](#mem.poly.allocator.ctor) Constructors [[mem.poly.allocator.ctor]](mem.poly.allocator.ctor) [🔗](#lib:polymorphic_allocator,constructor) `polymorphic_allocator() noexcept; ` [1](#mem.poly.allocator.ctor-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7728) *Effects*: Sets memory_rsrc to get_default_resource()[.](#mem.poly.allocator.ctor-1.sentence-1) [🔗](#lib:polymorphic_allocator,constructor_) `polymorphic_allocator(memory_resource* r); ` [2](#mem.poly.allocator.ctor-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7739) *Preconditions*: r is non-null[.](#mem.poly.allocator.ctor-2.sentence-1) [3](#mem.poly.allocator.ctor-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7743) *Effects*: Sets memory_rsrc to r[.](#mem.poly.allocator.ctor-3.sentence-1) [4](#mem.poly.allocator.ctor-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7747) *Throws*: Nothing[.](#mem.poly.allocator.ctor-4.sentence-1) [5](#mem.poly.allocator.ctor-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7751) [*Note [1](#mem.poly.allocator.ctor-note-1)*: This constructor provides an implicit conversion from memory_resource*[.](#mem.poly.allocator.ctor-5.sentence-1) — *end note*] [🔗](#lib:polymorphic_allocator,constructor__) `template polymorphic_allocator(const polymorphic_allocator& other) noexcept; ` [6](#mem.poly.allocator.ctor-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7763) *Effects*: Sets memory_rsrc to other.resource()[.](#mem.poly.allocator.ctor-6.sentence-1) #### [20.5.3.3](#mem.poly.allocator.mem) Member functions [[mem.poly.allocator.mem]](mem.poly.allocator.mem) [🔗](#lib:allocate,polymorphic_allocator) `Tp* allocate(size_t n); ` [1](#mem.poly.allocator.mem-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7777) *Effects*: If numeric_limits​::​max() / sizeof(Tp) < n, throws bad_array_new_length[.](#mem.poly.allocator.mem-1.sentence-1) Otherwise equivalent to:return static_cast(memory_rsrc->allocate(n * sizeof(Tp), alignof(Tp))); [🔗](#lib:deallocate,polymorphic_allocator) `void deallocate(Tp* p, size_t n); ` [2](#mem.poly.allocator.mem-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7793) *Preconditions*: p was allocated from a memory resource x, equal to *memory_rsrc, using x.allocate(n * sizeof(Tp), alignof(Tp))[.](#mem.poly.allocator.mem-2.sentence-1) [3](#mem.poly.allocator.mem-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7799) *Effects*: Equivalent to memory_rsrc->deallocate(p, n * sizeof(Tp), alignof(Tp))[.](#mem.poly.allocator.mem-3.sentence-1) [4](#mem.poly.allocator.mem-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7803) *Throws*: Nothing[.](#mem.poly.allocator.mem-4.sentence-1) [🔗](#lib:allocate_bytes,polymorphic_allocator) `void* allocate_bytes(size_t nbytes, size_t alignment = alignof(max_align_t)); ` [5](#mem.poly.allocator.mem-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7814) *Effects*: Equivalent to: return memory_rsrc->allocate(nbytes, alignment); [6](#mem.poly.allocator.mem-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7818) [*Note [1](#mem.poly.allocator.mem-note-1)*: The return type is void* (rather than, e.g., byte*) to support conversion to an arbitrary pointer type U* by static_cast, thus facilitating construction of a U object in the allocated memory[.](#mem.poly.allocator.mem-6.sentence-1) — *end note*] [🔗](#lib:deallocate_bytes,polymorphic_allocator) `void deallocate_bytes(void* p, size_t nbytes, size_t alignment = alignof(max_align_t)); ` [7](#mem.poly.allocator.mem-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7833) *Effects*: Equivalent to memory_rsrc->deallocate(p, nbytes, alignment)[.](#mem.poly.allocator.mem-7.sentence-1) [🔗](#lib:allocate_object,polymorphic_allocator) `template T* allocate_object(size_t n = 1); ` [8](#mem.poly.allocator.mem-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7845) *Effects*: Allocates memory suitable for holding an array of n objects of type T, as follows: - [(8.1)](#mem.poly.allocator.mem-8.1) if numeric_limits​::​max() / sizeof(T) < n, throws bad_array_new_length, - [(8.2)](#mem.poly.allocator.mem-8.2) otherwise equivalent to:return static_cast(allocate_bytes(n*sizeof(T), alignof(T))); [9](#mem.poly.allocator.mem-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7860) [*Note [2](#mem.poly.allocator.mem-note-2)*: T is not deduced and must therefore be provided as a template argument[.](#mem.poly.allocator.mem-9.sentence-1) — *end note*] [🔗](#lib:deallocate_object,polymorphic_allocator) `template void deallocate_object(T* p, size_t n = 1); ` [10](#mem.poly.allocator.mem-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7873) *Effects*: Equivalent to deallocate_bytes(p, n*sizeof(T), alignof(T))[.](#mem.poly.allocator.mem-10.sentence-1) [🔗](#lib:new_object,polymorphic_allocator) `template T* new_object(CtorArgs&&... ctor_args); ` [11](#mem.poly.allocator.mem-11) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7885) *Effects*: Allocates and constructs an object of type T, as follows[.](#mem.poly.allocator.mem-11.sentence-1) Equivalent to:T* p = allocate_object();try { construct(p, std::forward(ctor_args)...);} catch (...) { deallocate_object(p); throw;}return p; [12](#mem.poly.allocator.mem-12) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7900) [*Note [3](#mem.poly.allocator.mem-note-3)*: T is not deduced and must therefore be provided as a template argument[.](#mem.poly.allocator.mem-12.sentence-1) — *end note*] [🔗](#lib:new_object,polymorphic_allocator_) `template void delete_object(T* p); ` [13](#mem.poly.allocator.mem-13) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7913) *Effects*: Equivalent to:destroy(p); deallocate_object(p); [🔗](#lib:construct,polymorphic_allocator) `template void construct(T* p, Args&&... args); ` [14](#mem.poly.allocator.mem-14) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7929) *Mandates*: Uses-allocator construction of T with allocator *this (see [[allocator.uses.construction]](allocator.uses.construction "20.2.8.2 Uses-allocator construction")) and constructor arguments std​::​forward(args)... is well-formed[.](#mem.poly.allocator.mem-14.sentence-1) [15](#mem.poly.allocator.mem-15) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7935) *Effects*: Constructs a T object in the storage whose address is represented by p by uses-allocator construction with allocator *this and constructor arguments std​::​forward(args)...[.](#mem.poly.allocator.mem-15.sentence-1) [16](#mem.poly.allocator.mem-16) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7942) *Throws*: Nothing unless the constructor for T throws[.](#mem.poly.allocator.mem-16.sentence-1) [🔗](#lib:destroy,polymorphic_allocator) `template void destroy(T* p); ` [17](#mem.poly.allocator.mem-17) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7954) *Effects*: Equivalent to p->~T()[.](#mem.poly.allocator.mem-17.sentence-1) [🔗](#lib:select_on_container_copy_construction,polymorphic_allocator) `polymorphic_allocator select_on_container_copy_construction() const; ` [18](#mem.poly.allocator.mem-18) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7965) *Returns*: polymorphic_allocator()[.](#mem.poly.allocator.mem-18.sentence-1) [19](#mem.poly.allocator.mem-19) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7969) [*Note [4](#mem.poly.allocator.mem-note-4)*: The memory resource is not propagated[.](#mem.poly.allocator.mem-19.sentence-1) — *end note*] [🔗](#lib:resource,polymorphic_allocator) `memory_resource* resource() const; ` [20](#mem.poly.allocator.mem-20) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7981) *Returns*: memory_rsrc[.](#mem.poly.allocator.mem-20.sentence-1) #### [20.5.3.4](#mem.poly.allocator.eq) Equality [[mem.poly.allocator.eq]](mem.poly.allocator.eq) [🔗](#lib:operator==,polymorphic_allocator) `template bool operator==(const polymorphic_allocator& a, const polymorphic_allocator& b) noexcept; ` [1](#mem.poly.allocator.eq-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L7996) *Returns*: *a.resource() == *b.resource()[.](#mem.poly.allocator.eq-1.sentence-1) ### [20.5.4](#global) Access to program-wide memory_resource objects [[mem.res.global]](mem.res.global) [🔗](#lib:new_delete_resource) `memory_resource* new_delete_resource() noexcept; ` [1](#global-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8009) *Returns*: A pointer to a static-duration object of a type derived from memory_resource that can serve as a resource for allocating memory using ​::​operator new and ​::​operator delete[.](#global-1.sentence-1) The same value is returned every time this function is called[.](#global-1.sentence-2) For a return value p and a memory resource r,p->is_equal(r) returns &r == p[.](#global-1.sentence-3) [🔗](#lib:null_memory_resource) `memory_resource* null_memory_resource() noexcept; ` [2](#global-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8025) *Returns*: A pointer to a static-duration object of a type derived from memory_resource for which allocate() always throws bad_alloc and for which deallocate() has no effect[.](#global-2.sentence-1) The same value is returned every time this function is called[.](#global-2.sentence-2) For a return value p and a memory resource r,p->is_equal(r) returns &r == p[.](#global-2.sentence-3) [3](#global-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8035) The [*default memory resource pointer*](#def:default_memory_resource_pointer "20.5.4 Access to program-wide memory_­resource objects [mem.res.global]") is a pointer to a memory resource that is used by certain facilities when an explicit memory resource is not supplied through the interface[.](#global-3.sentence-1) Its initial value is the return value of new_delete_resource()[.](#global-3.sentence-2) [🔗](#lib:set_default_resource) `memory_resource* set_default_resource(memory_resource* r) noexcept; ` [4](#global-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8047) *Effects*: If r is non-null, sets the value of the default memory resource pointer to r, otherwise sets the default memory resource pointer to new_delete_resource()[.](#global-4.sentence-1) [5](#global-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8053) *Returns*: The previous value of the default memory resource pointer[.](#global-5.sentence-1) [6](#global-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8057) *Remarks*: Calling the set_default_resource andget_default_resource functions shall not incur a data race ([[intro.races]](intro.races "6.10.2.2 Data races"))[.](#global-6.sentence-1) A call to the set_default_resource function synchronizes with subsequent calls to the set_default_resource and get_default_resource functions[.](#global-6.sentence-2) [🔗](#lib:get_default_resource) `memory_resource* get_default_resource() noexcept; ` [7](#global-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8072) *Returns*: The current value of the default memory resource pointer[.](#global-7.sentence-1) ### [20.5.5](#pool) Pool resource classes [[mem.res.pool]](mem.res.pool) #### [20.5.5.1](#pool.overview) Classes synchronized_pool_resource and unsynchronized_pool_resource [[mem.res.pool.overview]](mem.res.pool.overview) [1](#pool.overview-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8081) The synchronized_pool_resource andunsynchronized_pool_resource classes (collectively called [*pool resource classes*](#def:pool_resource_classes "20.5.5.1 Classes synchronized_­pool_­resource and unsynchronized_­pool_­resource [mem.res.pool.overview]")) are general-purpose memory resources having the following qualities: - [(1.1)](#pool.overview-1.1) Each resource frees its allocated memory on destruction, even if deallocate has not been called for some of the allocated blocks[.](#pool.overview-1.1.sentence-1) - [(1.2)](#pool.overview-1.2) A pool resource consists of a collection of [*pools*](#def:pools "20.5.5.1 Classes synchronized_­pool_­resource and unsynchronized_­pool_­resource [mem.res.pool.overview]"), serving requests for different block sizes[.](#pool.overview-1.2.sentence-1) Each individual pool manages a collection of [*chunks*](#def:chunks "20.5.5.1 Classes synchronized_­pool_­resource and unsynchronized_­pool_­resource [mem.res.pool.overview]") that are in turn divided into blocks of uniform size, returned via calls to do_allocate[.](#pool.overview-1.2.sentence-2) Each call to do_allocate(size, alignment) is dispatched to the pool serving the smallest blocks accommodating at least size bytes[.](#pool.overview-1.2.sentence-3) - [(1.3)](#pool.overview-1.3) When a particular pool is exhausted, allocating a block from that pool results in the allocation of an additional chunk of memory from the [*upstream allocator*](#def:upstream_allocator "20.5.5.1 Classes synchronized_­pool_­resource and unsynchronized_­pool_­resource [mem.res.pool.overview]") (supplied at construction), thus replenishing the pool[.](#pool.overview-1.3.sentence-1) With each successive replenishment, the chunk size obtained increases geometrically[.](#pool.overview-1.3.sentence-2) [*Note [1](#pool.overview-note-1)*: By allocating memory in chunks, the pooling strategy increases the chance that consecutive allocations will be close together in memory[.](#pool.overview-1.3.sentence-3) — *end note*] - [(1.4)](#pool.overview-1.4) Allocation requests that exceed the largest block size of any pool are fulfilled directly from the upstream allocator[.](#pool.overview-1.4.sentence-1) - [(1.5)](#pool.overview-1.5) A pool_options struct may be passed to the pool resource constructors to tune the largest block size and the maximum chunk size[.](#pool.overview-1.5.sentence-1) [2](#pool.overview-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8118) A synchronized_pool_resource may be accessed from multiple threads without external synchronization and may have thread-specific pools to reduce synchronization costs[.](#pool.overview-2.sentence-1) An unsynchronized_pool_resource class may not be accessed from multiple threads simultaneously and thus avoids the cost of synchronization entirely in single-threaded applications[.](#pool.overview-2.sentence-2) [🔗](#lib:pool_options) namespace std::pmr {struct pool_options { size_t max_blocks_per_chunk = 0; size_t largest_required_pool_block = 0; }; class synchronized_pool_resource : public memory_resource {public: synchronized_pool_resource(const pool_options& opts, memory_resource* upstream); synchronized_pool_resource(): synchronized_pool_resource(pool_options(), get_default_resource()) {}explicit synchronized_pool_resource(memory_resource* upstream): synchronized_pool_resource(pool_options(), upstream) {}explicit synchronized_pool_resource(const pool_options& opts): synchronized_pool_resource(opts, get_default_resource()) {} synchronized_pool_resource(const synchronized_pool_resource&) = delete; virtual ~synchronized_pool_resource(); synchronized_pool_resource& operator=(const synchronized_pool_resource&) = delete; void release(); memory_resource* upstream_resource() const; pool_options options() const; protected:void* do_allocate(size_t bytes, size_t alignment) override; void do_deallocate(void* p, size_t bytes, size_t alignment) override; bool do_is_equal(const memory_resource& other) const noexcept override; }; class unsynchronized_pool_resource : public memory_resource {public: unsynchronized_pool_resource(const pool_options& opts, memory_resource* upstream); unsynchronized_pool_resource(): unsynchronized_pool_resource(pool_options(), get_default_resource()) {}explicit unsynchronized_pool_resource(memory_resource* upstream): unsynchronized_pool_resource(pool_options(), upstream) {}explicit unsynchronized_pool_resource(const pool_options& opts): unsynchronized_pool_resource(opts, get_default_resource()) {} unsynchronized_pool_resource(const unsynchronized_pool_resource&) = delete; virtual ~unsynchronized_pool_resource(); unsynchronized_pool_resource& operator=(const unsynchronized_pool_resource&) = delete; void release(); memory_resource* upstream_resource() const; pool_options options() const; protected:void* do_allocate(size_t bytes, size_t alignment) override; void do_deallocate(void* p, size_t bytes, size_t alignment) override; bool do_is_equal(const memory_resource& other) const noexcept override; };} #### [20.5.5.2](#pool.options) pool_options data members [[mem.res.pool.options]](mem.res.pool.options) [1](#pool.options-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8195) The members of pool_options comprise a set of constructor options for pool resources[.](#pool.options-1.sentence-1) The effect of each option on the pool resource behavior is described below: [🔗](#lib:pool_options,max_blocks_per_chunk) `size_t max_blocks_per_chunk; ` [2](#pool.options-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8206) The maximum number of blocks that will be allocated at once from the upstream memory resource ([[mem.res.monotonic.buffer]](#monotonic.buffer "20.5.6 Class monotonic_­buffer_­resource")) to replenish a pool[.](#pool.options-2.sentence-1) If the value of max_blocks_per_chunk is zero or is greater than an implementation-defined limit, that limit is used instead[.](#pool.options-2.sentence-2) The implementation may choose to use a smaller value than is specified in this member and may use different values for different pools[.](#pool.options-2.sentence-3) [🔗](#lib:pool_options,largest_required_pool_block) `size_t largest_required_pool_block; ` [3](#pool.options-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8224) The largest allocation size that is required to be fulfilled using the pooling mechanism[.](#pool.options-3.sentence-1) Attempts to allocate a single block larger than this threshold will be allocated directly from the upstream memory resource[.](#pool.options-3.sentence-2) If largest_required_pool_block is zero or is greater than an implementation-defined limit, that limit is used instead[.](#pool.options-3.sentence-3) The implementation may choose a pass-through threshold larger than specified in this member[.](#pool.options-3.sentence-4) #### [20.5.5.3](#pool.ctor) Constructors and destructors [[mem.res.pool.ctor]](mem.res.pool.ctor) [🔗](#lib:synchronized_pool_resource,constructor) `synchronized_pool_resource(const pool_options& opts, memory_resource* upstream); unsynchronized_pool_resource(const pool_options& opts, memory_resource* upstream); ` [1](#pool.ctor-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8246) *Preconditions*: upstream is the address of a valid memory resource[.](#pool.ctor-1.sentence-1) [2](#pool.ctor-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8250) *Effects*: Constructs a pool resource object that will obtain memory from upstream whenever the pool resource is unable to satisfy a memory request from its own internal data structures[.](#pool.ctor-2.sentence-1) The resulting object will hold a copy of upstream, but will not own the resource to which upstream points[.](#pool.ctor-2.sentence-2) [*Note [1](#pool.ctor-note-1)*: The intention is that calls to upstream->allocate() will be substantially fewer than calls to this->allocate() in most cases[.](#pool.ctor-2.sentence-3) — *end note*] The behavior of the pooling mechanism is tuned according to the value of the opts argument[.](#pool.ctor-2.sentence-4) [3](#pool.ctor-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8265) *Throws*: Nothing unless upstream->allocate() throws[.](#pool.ctor-3.sentence-1) It is unspecified if, or under what conditions, this constructor calls upstream->allocate()[.](#pool.ctor-3.sentence-2) [🔗](#lib:synchronized_pool_resource,destructor) `virtual ~synchronized_pool_resource(); virtual ~unsynchronized_pool_resource(); ` [4](#pool.ctor-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8280) *Effects*: Calls release()[.](#pool.ctor-4.sentence-1) #### [20.5.5.4](#pool.mem) Members [[mem.res.pool.mem]](mem.res.pool.mem) [🔗](#lib:release,synchronized_pool_resource) `void release(); ` [1](#pool.mem-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8294) *Effects*: Calls upstream_resource()->deallocate() as necessary to release all allocated memory[.](#pool.mem-1.sentence-1) [*Note [1](#pool.mem-note-1)*: The memory is released back to upstream_resource() even if deallocate has not been called for some of the allocated blocks[.](#pool.mem-1.sentence-2) — *end note*] [🔗](#lib:upstream_resource,synchronized_pool_resource) `memory_resource* upstream_resource() const; ` [2](#pool.mem-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8312) *Returns*: The value of the upstream argument provided to the constructor of this object[.](#pool.mem-2.sentence-1) [🔗](#lib:options,synchronized_pool_resource) `pool_options options() const; ` [3](#pool.mem-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8325) *Returns*: The options that control the pooling behavior of this resource[.](#pool.mem-3.sentence-1) The values in the returned struct may differ from those supplied to the pool resource constructor in that values of zero will be replaced with implementation-defined defaults, and sizes may be rounded to unspecified granularity[.](#pool.mem-3.sentence-2) [🔗](#lib:do_allocate,synchronized_pool_resource) `void* do_allocate(size_t bytes, size_t alignment) override; ` [4](#pool.mem-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8341) *Effects*: If the pool selected for a block of size bytes is unable to satisfy the memory request from its own internal data structures, it will call upstream_resource()->allocate() to obtain more memory[.](#pool.mem-4.sentence-1) If bytes is larger than that which the largest pool can handle, then memory will be allocated using upstream_resource()->allocate()[.](#pool.mem-4.sentence-2) [5](#pool.mem-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8349) *Returns*: A pointer to allocated storage ([[basic.stc.dynamic.allocation]](basic.stc.dynamic.allocation "6.8.6.5.2 Allocation functions")) with a size of at least bytes[.](#pool.mem-5.sentence-1) The size and alignment of the allocated memory shall meet the requirements for a class derived from memory_resource ([[mem.res.class]](#class "20.5.2 Class memory_­resource"))[.](#pool.mem-5.sentence-2) [6](#pool.mem-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8356) *Throws*: Nothing unless upstream_resource()->allocate() throws[.](#pool.mem-6.sentence-1) [🔗](#lib:do_deallocate,synchronized_pool_resource) `void do_deallocate(void* p, size_t bytes, size_t alignment) override; ` [7](#pool.mem-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8368) *Effects*: Returns the memory at p to the pool[.](#pool.mem-7.sentence-1) It is unspecified if, or under what circumstances, this operation will result in a call to upstream_resource()->deallocate()[.](#pool.mem-7.sentence-2) [8](#pool.mem-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8374) *Throws*: Nothing[.](#pool.mem-8.sentence-1) [🔗](#lib:do_is_equal,synchronized_pool_resource) `bool do_is_equal(const memory_resource& other) const noexcept override; ` [9](#pool.mem-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8386) *Returns*: this == &other[.](#pool.mem-9.sentence-1) ### [20.5.6](#monotonic.buffer) Class monotonic_buffer_resource [[mem.res.monotonic.buffer]](mem.res.monotonic.buffer) #### [20.5.6.1](#monotonic.buffer.general) General [[mem.res.monotonic.buffer.general]](mem.res.monotonic.buffer.general) [1](#monotonic.buffer.general-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8395) A monotonic_buffer_resource is a special-purpose memory resource intended for very fast memory allocations in situations where memory is used to build up a few objects and then is released all at once when the memory resource object is destroyed[.](#monotonic.buffer.general-1.sentence-1) [🔗](#lib:monotonic_buffer_resource) namespace std::pmr {class monotonic_buffer_resource : public memory_resource { memory_resource* upstream_rsrc; // *exposition only*void* current_buffer; // *exposition only* size_t next_buffer_size; // *exposition only*public:explicit monotonic_buffer_resource(memory_resource* upstream); monotonic_buffer_resource(size_t initial_size, memory_resource* upstream); monotonic_buffer_resource(void* buffer, size_t buffer_size, memory_resource* upstream); monotonic_buffer_resource(): monotonic_buffer_resource(get_default_resource()) {}explicit monotonic_buffer_resource(size_t initial_size): monotonic_buffer_resource(initial_size, get_default_resource()) {} monotonic_buffer_resource(void* buffer, size_t buffer_size): monotonic_buffer_resource(buffer, buffer_size, get_default_resource()) {} monotonic_buffer_resource(const monotonic_buffer_resource&) = delete; virtual ~monotonic_buffer_resource(); monotonic_buffer_resource& operator=(const monotonic_buffer_resource&) = delete; void release(); memory_resource* upstream_resource() const; protected:void* do_allocate(size_t bytes, size_t alignment) override; void do_deallocate(void* p, size_t bytes, size_t alignment) override; bool do_is_equal(const memory_resource& other) const noexcept override; };} #### [20.5.6.2](#monotonic.buffer.ctor) Constructors and destructor [[mem.res.monotonic.buffer.ctor]](mem.res.monotonic.buffer.ctor) [🔗](#lib:monotonic_buffer_resource,constructor) `explicit monotonic_buffer_resource(memory_resource* upstream); monotonic_buffer_resource(size_t initial_size, memory_resource* upstream); ` [1](#monotonic.buffer.ctor-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8448) *Preconditions*: upstream is the address of a valid memory resource[.](#monotonic.buffer.ctor-1.sentence-1) initial_size, if specified, is greater than zero[.](#monotonic.buffer.ctor-1.sentence-2) [2](#monotonic.buffer.ctor-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8453) *Effects*: Sets upstream_rsrc to upstream andcurrent_buffer to nullptr[.](#monotonic.buffer.ctor-2.sentence-1) If initial_size is specified, sets next_buffer_size to at least initial_size; otherwise sets next_buffer_size to animplementation-defined size[.](#monotonic.buffer.ctor-2.sentence-2) [🔗](#lib:monotonic_buffer_resource,constructor_) `monotonic_buffer_resource(void* buffer, size_t buffer_size, memory_resource* upstream); ` [3](#monotonic.buffer.ctor-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8469) *Preconditions*: upstream is the address of a valid memory resource[.](#monotonic.buffer.ctor-3.sentence-1) buffer_size is no larger than the number of bytes in buffer[.](#monotonic.buffer.ctor-3.sentence-2) [4](#monotonic.buffer.ctor-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8474) *Effects*: Sets upstream_rsrc to upstream,current_buffer to buffer, andnext_buffer_size to buffer_size (but not less than 1), then increases next_buffer_size by an implementation-defined growth factor (which need not be integral)[.](#monotonic.buffer.ctor-4.sentence-1) [🔗](#lib:monotonic_buffer_resource,destructor) `~monotonic_buffer_resource(); ` [5](#monotonic.buffer.ctor-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8489) *Effects*: Calls release()[.](#monotonic.buffer.ctor-5.sentence-1) #### [20.5.6.3](#monotonic.buffer.mem) Members [[mem.res.monotonic.buffer.mem]](mem.res.monotonic.buffer.mem) [🔗](#lib:release,monotonic_buffer_resource) `void release(); ` [1](#monotonic.buffer.mem-1) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8503) *Effects*: Calls upstream_rsrc->deallocate() as necessary to release all allocated memory[.](#monotonic.buffer.mem-1.sentence-1) Resets current_buffer and next_buffer_size to their initial values at construction[.](#monotonic.buffer.mem-1.sentence-2) [2](#monotonic.buffer.mem-2) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8510) [*Note [1](#monotonic.buffer.mem-note-1)*: The memory is released back to upstream_rsrc even if some blocks that were allocated from *this have not been deallocated from *this[.](#monotonic.buffer.mem-2.sentence-1) — *end note*] [🔗](#lib:upstream_resource,monotonic_buffer_resource) `memory_resource* upstream_resource() const; ` [3](#monotonic.buffer.mem-3) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8524) *Returns*: The value of upstream_rsrc[.](#monotonic.buffer.mem-3.sentence-1) [🔗](#lib:do_allocate,monotonic_buffer_resource) `void* do_allocate(size_t bytes, size_t alignment) override; ` [4](#monotonic.buffer.mem-4) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8535) *Effects*: If the unused space in current_buffer can fit a block with the specified bytes and alignment, then allocate the return block from current_buffer; otherwise set current_buffer to upstream_rsrc->allocate(n, m), where n is not less than max(bytes, next_buffer_size) andm is not less than alignment, and increase next_buffer_size by an implementation-defined growth factor (which need not be integral), then allocate the return block from the newly-allocated current_buffer[.](#monotonic.buffer.mem-4.sentence-1) [5](#monotonic.buffer.mem-5) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8547) *Returns*: A pointer to allocated storage ([[basic.stc.dynamic.allocation]](basic.stc.dynamic.allocation "6.8.6.5.2 Allocation functions")) with a size of at least bytes[.](#monotonic.buffer.mem-5.sentence-1) The size and alignment of the allocated memory shall meet the requirements for a class derived from memory_resource ([[mem.res.class]](#class "20.5.2 Class memory_­resource"))[.](#monotonic.buffer.mem-5.sentence-2) [6](#monotonic.buffer.mem-6) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8554) *Throws*: Nothing unless upstream_rsrc->allocate() throws[.](#monotonic.buffer.mem-6.sentence-1) [🔗](#lib:do_deallocate,monotonic_buffer_resource) `void do_deallocate(void* p, size_t bytes, size_t alignment) override; ` [7](#monotonic.buffer.mem-7) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8565) *Effects*: None[.](#monotonic.buffer.mem-7.sentence-1) [8](#monotonic.buffer.mem-8) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8569) *Throws*: Nothing[.](#monotonic.buffer.mem-8.sentence-1) [9](#monotonic.buffer.mem-9) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8573) *Remarks*: Memory used by this resource increases monotonically until its destruction[.](#monotonic.buffer.mem-9.sentence-1) [🔗](#lib:do_is_equal,monotonic_buffer_resource) `bool do_is_equal(const memory_resource& other) const noexcept override; ` [10](#monotonic.buffer.mem-10) [#](http://github.com/Eelis/draft/tree/9adde4bc1c62ec234483e63ea3b70a59724c745a/source/memory.tex#L8584) *Returns*: this == &other[.](#monotonic.buffer.mem-10.sentence-1)