7-6 Пул объектов (object_pool)
оценка 10
Просмотр тем в полноэкранном режиме
переключить раскладку
Автор Ван Чжэн Юнит Шаньдунский университет
В Java есть функция сборки мусора (GC), которая может освобождать такие ресурсы, как память и объекты, которые больше нельзя использовать. Но C++ сам отвечает за освобождение динамически выделяемых ресурсов. Как разработчик программного обеспечения я чувствую, что бремя на моих плечах еще тяжелее. Так как же реализовано управление ресурсами? Я нашел решение начального уровня для реализации пула объектов с использованием технологии свободных списков .
Например, если имеется пул объектов C с емкостью Object pool[C + 1] (№ 0 — это фиктивный элемент, который не используется), используйте свободный список для управления им. Говорят, что связный список C++ должен использовать всеми любимые и уважаемые указатели , но указатели только что были упомянуты, и уже слишком поздно, поэтому я сначала использую индекс массива для имитации указателей.
Создайте главный индекс и массив-наследник списка свободных : int head = 1, next[C + 1];
head равен 0 означает, что свободного юнита нет, в противном случае это означает индекс следующего свободного юнита
Инициализация: next[1] = 2, next[2] = 3, ... next[C] = 0;
Моделируйте, используя:
Объект размещения: новый
Если head == 0, доступных юнитов нет, просто верните 0.
Если head != 0, используйте p, чтобы сохранить текущее значение head, измените head на next[head] и верните p, чтобы указать, что объект pool[p] можно использовать.
Справочный объект: ref p
Если p действителен (в диапазоне [1, C] и был выделен), выведите ok
иначе ошибка
Освободить объект: удалить p
Если p == 0, просто выведите голову. C/C++ оговаривается таким образом, позволяя освобождать (NULL) или удалять nullptr).
Если p != 0, запрашивается возврат блока pool[p]:
Если p действителен (в диапазоне [1, C] и был выделен), поместите его в начало списка свободных мест: next[p] = head; head = p;.
Если неверно, вывести ошибку
Цель: попрактиковаться в методах работы с массивами, циклами, моделированием событий и свободными связными списками; помочь в понимании указателей.
входные характеристики
В первой строке задается емкость C пула объектов, где C — целое положительное число, меньшее 65536.
Последующие запросы на выделение и освобождение нескольких строк обрабатываются до EOF. Количество запросов меньше 65536.
новая операция распределения
ref x относится к единице x
удалить x освобождает блок x
выходная спецификация
Первая строка вывода: capacity <C> # head=1
Затем обработайте операции одну за другой:
Вывести операцию и параметры, пробел, #, пробел, результат операции как есть
Результаты операции следующие:
Распределение: new # return <p>, head=<h> Выведите индекс выделенного модуля p и индекс свободного заголовка h после выделения.
Возвращает 0, если нет свободных ячеек.
Цитата: ref<p> # ок или ref <p> # ошибка
освобожден:
delete <p> # head=<h>, где p — индекс освобожденной единицы, а h — скорректированный индекс свободной головки.
Если p недействителен, выведите ошибку
образец ввода
capacity 2
new
ref 1
new
new
delete 2
ref 2
delete 2
delete 9
delete 0
new
delete 1
new
delete 1
delete 2
образец вывода
capacity 2 # head=1
new # return 1, head=2
ref 1 # ok
new # return 2, head=0
new # return 0, head=0
delete 2 # head=2
ref 2 # error
delete 2 # error
delete 9 # error
delete 0 # head=2
new # return 2, head=0
delete 1 # head=1
new # return 1, head=0
delete 1 # head=1
delete 2 # head=2
Ограничение длины кода 16 КБ
Ограничение по времени 400 мс
Ограничение памяти 64 МБ
Отвечать
#include<iostream>
#include<vector>
#include <bitset>
using namespace std;
template<typename T>
class ObjectPool
{
private:
vector<T*> pool;
bitset<65537> is_vaid;
int head = 1,C;
vector<int> next;
public:
ObjectPool(int c)
{
C = c;
for (int i = 0; i < c; ++i)
{
next.push_back(i+1);
pool.push_back(new T());
is_vaid[i] = 0;
}
pool.push_back(new T());
next.push_back(0);
}
int createNew()
{
if (head == 0)return 0;
else if (head != 0)
{
int p;
p = head;
head = next[head];
is_vaid[p] = 1;
//printf("\n2\n");
return p;
}
return 0;
}
T* ref(int p)
{
//cout << endl << "h" << endl;
if (p<1 || p>C)return nullptr;
//cout << endl << "h" << endl;
if (is_vaid[p]==1)
{
//cout << endl << pool[p] << endl;
return pool[p];
}
return nullptr;
}
int deleteObject(int p)
{
if (p == 0)return head;
else
{
if (p >= 1 && p <= C && is_vaid[p]==1)
{
next[p] = head;
head = p;
return head;
}
}
return 0;
}
int getHead()
{
//printf("\n1\n");
return head;
}
};
int main()
{
int C,i;
scanf("capacity %d", &C);
ObjectPool<int>* object_pool = new ObjectPool<int>(C);
int* int_ptr=nullptr;
char c;
c = getchar();
while (c != EOF)
{
c = getchar();
switch (c)
{
case 'n':
scanf("ew");
i = object_pool->createNew();
printf("new # return %d, head=%d\n", i, object_pool->getHead());
break;
case 'r':
scanf("ef %d", &i);
int_ptr =object_pool->ref(i);
if (int_ptr == nullptr)
{
printf("ref %d # error\n", i);
}
else
{
printf("ref %d # ok\n", i);
}
break;
case 'd':
scanf("elete %d", &i);
if (object_pool->deleteObject(i) !=0)
{
printf("delete %d # head=%d\n", i, object_pool->getHead());
}
else
{
printf("delete %d # error\n", i);
}
break;
case EOF:
return 0;
}
}
}