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. It has the following qualities:
A call to deallocate has no effect, thus the amount of memory consumed increases monotonically until the resource is destroyed.
The program can supply an initial buffer, which the allocator uses to satisfy memory requests.
When the initial buffer (if any) is exhausted, it obtains additional buffers from an upstream memory resource supplied at construction. Each additional buffer is larger than the previous one, following a geometric progression.
It is intended for access from one thread of control at a time. Specifically, calls to allocate and deallocate do not synchronize with one another.
It frees the allocated memory on destruction, even if deallocate has not been called for some of the allocated blocks.
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; };
explicit monotonic_buffer_resource(memory_resource* upstream);
monotonic_buffer_resource(size_t initial_size, memory_resource* upstream);
Requires: upstream shall be the address of a valid memory resource. initial_size, if specified, shall be greater than zero.
monotonic_buffer_resource(void* buffer, size_t buffer_size, memory_resource* upstream);
Requires: upstream shall be the address of a valid memory resource. buffer_size shall be no larger than the number of bytes in buffer.
~monotonic_buffer_resource();
void release();
[ Note: The memory is released back to upstream_rsrc even if some blocks that were allocated from this have not been deallocated from this. — end note ]
memory_resource* upstream_resource() const;
void* do_allocate(size_t bytes, size_t alignment) override;
Returns: A pointer to allocated storage ([basic.stc.dynamic.deallocation]) with a size of at least bytes. The size and alignment of the allocated memory shall meet the requirements for a class derived from memory_resource.
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) and m 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.
void do_deallocate(void* p, size_t bytes, size_t alignment) override;
bool do_is_equal(const memory_resource& other) const noexcept override;