Блок задач

8. Чёрные ящики

Темы
Сложность 5

Задача «Пул объектов»

Реализовать контейнер, содержащий в себе фиксированный набор объектов, готовых к использованию.

Описание

Пул объектов используется:

  • для повышения производительности, когда создание объекта в начале работы и уничтожение его в конце приводит к большим затратам времени / памяти;
  • в случае, когда объекты часто создаются и уничтожаются, но одновременно существует лишь небольшое их количество.

В пуле объекты создаются / уничтожаются в 2 этапа. Первичная инициализация / деинициализация — это дорогостоящая операция и производится только при создании уничтожении всего пула объектов. Финальная инициализация / деинициализация считается более дешёвой операцией и выполняется непосредственно перед запросом из пула / после возвращения в пул объекта.

В рамках задачи считаем выделение памяти дорогой, а вызов конструктора — дешёвой операцией.

Примерный интерфейс контейнера:

  • Конструктор: указывается количество объектов в пуле (в дальнейшем их количество не изменяется). Производится частичная инициализация объектов (выделяется память).
  • alloc(): производится окончательная инициализация объекта (вызывается конструктор объекта), объект помечается как занятый, пользователю возвращается ссылка на объект. Если свободных объектов в пуле нет — генерируется исключение.
  • free(): производится частичная деинициализация (вызывается деструктор), объект помечается как свободный.
  • Деструктор: все объекты в пуле деинициализируются (у занятых объектов вызывается деструктор). Производится полное удаление всех объектов (освобождается память).

По аналогии с методом std::vector.emplace, процедура запроса должна предусматривать передачу дополнительных параметров, необходимых для окончательной инициализации объекта.

class Point {
    int m_x, m_y;
public:
    Point()                // конструктор без параметров
        : m_x(0), m_y(0) {}
    Point(int x, int y)    // конструктор с параметрами
        : m_x(x), m_y(y) {}
};

ObjectPool<Point> pp(10);     // выделена память под 10 объектов Point

Point &p1 = pp.alloc();       // сработал конструктор Point()
Point &p2 = pp.alloc(0, 1);   // сработал конструктор Point(0, 1)