23 General utilities library [utilities]

23.12 Memory resources [mem.res]

23.12.5 Pool resource classes [mem.res.pool]

23.12.5.1 Classes synchronized_­pool_­resource and unsynchronized_­pool_­resource [mem.res.pool.overview]

В synchronized_­pool_­resource и unsynchronized_­pool_­resource классах (вместе называемые pool resource classes) являются ресурсами памяти общего назначения , имеющие следующие свойства:

  • Каждый ресурс освобождает свою выделенную память при уничтожении, даже если deallocate не был вызван для некоторых из выделенных блоков.

  • Ресурс пула состоит из набора pools, обслуживающего запросы для блоков разного размера. Каждый отдельный пул управляет коллекцией, chunks которая, в свою очередь, разделена на блоки одинакового размера, которые возвращаются через вызовы do_­allocate. Каждый вызов do_­allocate(size, alignment) отправляется в пул, обслуживающий самые маленькие блоки, вмещающие не менее size байтов.

  • Когда конкретный пул исчерпан, выделение блока из этого пула приводит к выделению дополнительного фрагмента памяти из upstream allocator (предоставленного при построении), таким образом пополняя пул. При каждом последующем пополнении размер получаемого блока увеличивается геометрически. [ Note: Распределяя память по частям, стратегия объединения увеличивает вероятность того, что последовательные распределения будут близки друг к другу в памяти. ] end note

  • Запросы на выделение, превышающие самый большой размер блока любого пула, выполняются непосредственно из вышестоящего распределителя.

  • pool_­options Структура может быть передана в конструкторах пул ресурсов для настройки самого большого размера блока и максимальный размер порции.

synchronized_­pool_­resource Доступ к A может осуществляться из нескольких потоков без внешней синхронизации, и он может иметь пулы, зависящие от потока, для снижения затрат на синхронизацию. К unsynchronized_­pool_­resource классу нельзя получить доступ из нескольких потоков одновременно, что позволяет полностью избежать затрат на синхронизацию в однопоточных приложениях.

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