23 General utilities library [utilities]

23.12 Memory resources [mem.res]

23.12.6 Class monotonic_­buffer_­resource [mem.res.monotonic.buffer]

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;
};

23.12.6.1 monotonic_­buffer_­resource constructor and destructor [mem.res.monotonic.buffer.ctor]

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.
Effects: Sets upstream_­rsrc to upstream and current_­buffer to nullptr.
If initial_­size is specified, sets next_­buffer_­size to at least initial_­size; otherwise sets next_­buffer_­size to an implementation-defined size.
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.
Effects: Sets upstream_­rsrc to upstream, current_­buffer to buffer, and next_­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_resource();
Effects: Calls release().

23.12.6.2 monotonic_­buffer_­resource members [mem.res.monotonic.buffer.mem]

void release();
Effects: Calls upstream_­rsrc->deallocate() as necessary to release all allocated memory.
[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;
Returns: The value of upstream_­rsrc.
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 ([mem.res]).
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.
Throws: Nothing unless upstream_­rsrc->allocate() throws.
void do_deallocate(void* p, size_t bytes, size_t alignment) override;
Effects: None.
Throws: Nothing.
Remarks: Memory used by this resource increases monotonically until its destruction.
bool do_is_equal(const memory_resource& other) const noexcept override;
Returns: this == dynamic_­cast<const monotonic_­buffer_­resource*>(&other).