С++ - язык, который изучается постепенно.ГЛАВА 15. Пространства объектов


Материалы книги получены с http://www.itlibitum.ru/

Пространства объектов

Половины представлены в виде пространств памяти для создания объектов. Класс HalfSpace

изображает одну половину, а Space - всю память, видимую клиентам.

Класс HalfSpace

Каждая половина по отдельности выглядит как обычное пространство памяти со специализированной функцией Allocate(). Парная функция Deallocate() не понадобится.

class HalfSpace {

private:

unsigned long next_byte; // Следующий выделяемый байт

unsigned char bytes[HALFSIZE];

public:

HalfSpace() : next_byte(0) {}

void* Allocate(size_t size);

void Reinitialize() { next_byte = 0; }

};

void* HalfSpace::Allocate(size_t size)

{

// Выровнять до границы слова

size = ROUNDUP(size);

if (next_byte + size >= HALFSIZE)

return NULL; // Не хватает памяти

void* space = &bytes[next_byte];

next_byte += size;

return space;

}

Класс Space

Общий пул представляет собой совокупность двух половин. Он также имеет функцию  Allocate(), которая в обычных ситуациях просто поручает работу активной половине. Если в активной половине не найдется достаточно памяти, происходит переключение половин и копирование активных объектов в другую половину функцией Swap(). Эта схема основана на предыдущем материале - специализированном пуле VoidPtr со средствами перебора.

class Space {

private:

HalfSpace A, B;

HalfSpace* active;

HalfSpace* inactive;

void Swap(); // Переключить активную половину, скопировать объекты

public:

Space() : active(&A), inactive(&B) {};

void* Allocate(size_t size);

};

void* Space::Allocate(size_t size)

{

void* space = active->Allocate(size);

if (space != NULL) return space;

Swap();

Space = active->Allocate(size);

if (space == NULL)

// Исключение - нехватка памяти

return space;

}

void Space::Swap()

{

if (active == &A)

{

active = &B;

inactive = &A;

}

else

{

active = &A;

inactive = &B;

}

active->Reinitialize();

// Перебрать все VoidPtr и найте активные объекты

VoidPtrIterator* iterator = VoidPtr::pool->iterator();

while (iterator->More())

{

VoidPtr* vp = iterator->Next();

if (vp->address >= inactive &&

vp->address < inactive + sizeof(*inactive))

{

void* new_space = active->Allocate(vp->size);

if (new_space == NULL)

// Исключение - нехватка памяти

memcpy(new_space, vp->address, vp->size);

vp->address = new_space;

}

}

delete iterator;

}

Все существенное происходит в цикле while функции Space::Swap(). Каждый объект в предыдущей, ранее активной половине копируется в новую активную половину. Вскоре вы поймете, зачем мы проверяем, принадлежит ли адрес старой половине.

Оператор new

Конечно, у нас появляется перегруженный оператор new, который использует эту структуру.

void* operator new(size_t size, Space* space)

{

return space->Allocate(size);

}

Ведущие указатели

Наконец, ведущие указатели должны использовать это пространство при создании объектов.

template <class Type>

class BMP : public VoidPtr {

private: // Запретить копирование и присваивание указателей

BMP(const MP<Type>&) {}

BMP<Type>& operator=(const BMP<Type>&) { return *this; }

public:

BMP() : VoidPtr(new(object_space) Type, sizeof(Type)) {}

virtual ~BMP() { ((Type*)address->Type::~Type(); }

Type* operator->() { return (Type*)address; }

};

Здесь object_space - глобальная переменная (а может быть, статическая переменная класса VoidPtr), которая ссылается на рабочее пространство Space.


Назад    Содержание    Далее    

Copyright 2005. Климов Александр. All Right Reserved.
Сайт создан в системе uCoz