[mem.res.pool.overview]

# 20 Memory management library [[mem]](./#mem)

## 20.5 Memory resources [[mem.res]](mem.res#pool.overview)

### 20.5.5 Pool resource classes [[mem.res.pool]](mem.res.pool#overview)

#### 20.5.5.1 Classes synchronized_pool_resource and unsynchronized_pool_resource [mem.res.pool.overview]

[1](#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)](#1.1)

  Each resource frees its allocated memory on destruction,
even if deallocate has not been called for some of the allocated blocks[.](#1.1.sentence-1)

- [(1.2)](#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[.](#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[.](#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[.](#1.2.sentence-3)

- [(1.3)](#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[.](#1.3.sentence-1)
  With each successive replenishment,
the chunk size obtained increases geometrically[.](#1.3.sentence-2)
  [*Note [1](#note-1)*:
  By allocating memory in chunks,
the pooling strategy increases the chance that consecutive allocations
will be close together in memory[.](#1.3.sentence-3)
 â *end note*]

- [(1.4)](#1.4)

  Allocation requests that exceed the largest block size of any pool
are fulfilled directly from the upstream allocator[.](#1.4.sentence-1)

- [(1.5)](#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[.](#1.5.sentence-1)

[2](#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[.](#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[.](#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; };}
