237
указываемых объектов. Конструкторы (см. далее) напрямую работают с переменной
VoidPtrPool::tail
. Деструктор исключает экземпляр из списка. Во всем остальном класс
VoidPtr
остался прежним. Ниже показаны изменения в
VoidPtr
.
class VoidPtr {
private:
//
Новые переменные для ведения списка
VoidPtr*
next;
//
Следующий элемент списка
VoidPtr*
previous;
//
Предыдущий элемент списка
protected:
//
Изменившиеся конструкторы
VoidPtr() : address(NULL), size(0), refcount(0),
next(NULL), previous(NULL) {}
VoidPtr(void* addr, size_t s) : address(addr), size(s), refcount(0),
next(NULL),
previous(pool->tail->previous)
{
pool->tail->next = this;
pool->tail
=
this;
}
public:
//
Измененный деструктор
virtual
~VoidPtr()
{
if (size != 0)
// Активный указатель – исключить из списка
{
if
(previous
!=
NULL)
previous->next
=
next;
if (next != NULL)
next->previous
=
previous;
if (pool->tail == this)
pool->tail
=
previous;
}
size = 0;
address = NULL;
}
};
Пул ведущих указателей
Изменения в пуле ведущих указателей
VoidPtrPool
также весьма тривиальны.
class VoidPtrPool {
// Как и прежде, плюс следующее
friend class VoidPtr; // Обеспечивает доступ к tail
private:
//
Новые переменные для ведения списка
VoidPtr
head;
//
Фиктивный VoidPtr, который ссылается
// на список активных указателей
VoidPtr*
tail;
//
Конец списка
public:
//
Новая версия конструктора
VoidPtrPool() : block_list(NULL), free_list(NULL), tail(&head) {}
};
238
Класс
VoidPtrPool
идентичен тому, который использовался в алгоритме Бейкера, с добавлением
связанного списка активных
VoidPtr
.
Итератор ведущих указателей
Итератор ведущих указателей устроен элементарно. Он просто перебирает элементы списка от начала
к концу — иначе говоря, от нижних адресов памяти к верхним.
class VoidPtrPoolIterator : public VoidPtrIterator {
private:
VoidPtr*
next;
public:
VoidPtrIterator(VoidPtr* first) : next(first) {}
virtual bool More() { return next != NULL; }
virtual VoidPtr* Next()
{
VoidPtr* vp = next;
next = next->next;
return
vp;
}
};
VoidPtrIterator* VoidPtrPool::iterator()
{
return
new
VoidPtrPoolIterator(&head.next);
}
Алгоритм уплотнения
Алгоритм уплотнения выглядит так просто, что его можно было бы и не приводить.
class Space {
private:
unsigned long next_byte;
unsigned char bytes[SPACESIZE];
public:
Space() : next_byte(0) {}
void*
Allocate(size_t
size);
void
Compact();
};
void* Space::Allocate(size_t size)
{
//
Выровнять на границу слова
size = ROUNDUP(size);
if (next_byte + size > SPACESIZE)
{
Compact();
if (next_byte + size > SPACESIZE)
//
Исключение – нехватка памяти
}
void* space = &bytes[next_byte];
next_byte += size;
return
space;
}
Do'stlaringiz bilan baham: |