Программирование >>  Синтаксис инициирования исключений 

1 ... 76 77 78 [ 79 ] 80 81 82


дальнейшие манипуляции с ним. Объекты, не принадлежащие ни одной из половин, мы пока игнорируем.

Интерфейс Space слегка отличается от того, который использовался для уплотнения. Вместо одного итератора приходится поддерживать стек итераторов, поскольку мы перемещаемся по графу объектов. Кроме того, появилась новая функция Scavenge() , которая вызывается в конце каждого прохода по половине. Предполагается, что у нас уже имеется готовый шаблон стека Stack.

template <c1ass Type> class Stack { public:

Push(Type*);

Type* Pop(); Возвращает NULL для пустого стека

class Space { private:

VoidPtrIterator* iterator; Итератор верхнего уровня

Stack<VoidPtrIterator> iterator stack; HalfSpace A, B; HalfSpace* active; HalfSpace* inactive;

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

public:

Space() : active(&a), inactive(&B), iterator(NULL) { Swap(); } void* Al1ocate(size t size)

void* space = active->Al1ocate(size); if (space == NULL) throw(OutOfMemory()); return space;

void Copy1();

Три ключевые функции - Scavenge() , Swap() и Copy1() - ниже рассматриваются более подробно. Scavenge

Функция Scavenge() вызывается после одного полного цикла. Она перебирает все ведущие указатели и ищет объекты, оставшиеся в неактивной половине. Эти объекты недоступны. Для каждого объекта она удаляет указатель, который, в свою очередь, вызывает деструктор объекта.

void Space::Scanvege()

VoidPtrIterator* vpi =

VoidPtr::poo1->InRange(inactive, inactive + sizeof(*inactive)); while (vpi->More()) {

VoidPtr* vp = vpi->Next();

delete vp; Вызывает деструктор указываемого объекта

delete vpi;



Swap

Функция Swap() переключает активную половину. Сначала она вызывает Scavenge() в завершение предыдущего цикла, а потом сбрасывает все в исходное состояние, чтобы при следующем вызове функции Copy1() копирование пошло в обратную сторону.

void Space::Swap()

Scavenge(); Уничтожить объекты в неактивной половине if (active == &A)

active = &B; inactive = &A;

else

active = &A; inactive = &B;

active->Rei nitia1ize();

iterator = VoidPtr::poo1->iterator();

Copy1

Функция Copy1() рассматривает один объект. Если объект находится в неактивной половине, он копируется в активную. Если объекта нет, то в рамках текущей задачи мы предполагаем, что он находится в активной половине, а следовательно, был перемещен ранее.

void Space::Copy1()

if (!iterator->More())

Перебор закончен, удалить итератор и вытолкнуть из стека delete iterator;

iterator = iterator stack.Pop();

if (iterator == NULL) Готово!

Swap(); Начинаем двигаться в другую сторону

else

VoidPtr* vp = iterator->Next(); if (vp->address >= &inactive &&

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

Объект доступен и его нужно переместить void* new space = active->Al1ocate(vp->size); if (new space == NULL)

Исключение - нехватка памяти memcpy(new space, vp->address, vp->size); vp->address = new space; iterator stack.Push(iterator); iterator = vp->address->Pointers();



Оптимизация

Только что описанный алгоритм способен резко тормозить программу при каждом запуске функции Scavenge(). Для оптимизации по отдельности или вместе могут использоваться два следующих подхода:

1 . Функция Scavenge() работает поэтапно, а не как единая операция. Для этого вам придется модифицировать Copy1() , чтобы ее последовательный аналог вызывался до завершения сборки мусора.

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

Вряд ли эти варианты оптимизации стоит применять в реальных проектах - особенно второй, поскольку ведение списков потребует значительно больших затрат памяти и быстродействия.

Внешние объекты

Объекты, которые существуют за пределами пространства сборки мусора, слегка усложняют нашу задачу. Объекты внутри пространства могут ссылаться на эти внешние объекты. Само по себе это не вызовет проблем, поскольку перемещаются только объекты неактивной половины. Проблемы возникают в ситуациях, когда внешние объекты ссылаются на внутренние. Вероятно, они будут использовать дескрипторы, но это заметно повысит сложность алгоритма сборки мусора/уплотнения. Потребуются следующие изменения:

1 . Каждый внешний объект также должен обладать средствами перебора указателей и соблюдать правило дескрипторы повсюду , по крайней мере для ссылок на внутренние объекты.

2. Каждый внешний объект во время очередного прохода должен уметь помечать себя как просмотренный.

3. Если объект в функции Copy1() является внешним и непомеченным, он помечается, а его итератор заносится в стек, но сам объект при этом не перемещается.

Множественные пространства

Когда базовая структура будет налажена, объекты в пространстве сборки мусора можно без особых проблем объединить с объектами, управляемыми другими средствами. Главное - чтобы все объекты сотрудничали в процессе перебора указателей. Способ управления объектом легко определяется по его адресу.

Сборка мусора и уплотнение на месте

Решения из предыдущей главы, которые помогли нам превратить схему дескрипторы повсюду в уплотнение на месте, можно применить и в данной схеме. Это позволит организовать сборку мусора на месте и обойтись без копирования объектов в памяти. Существуют два варианта этой схемы: с уплотнением и без. В обоих случаях используется алгоритм пометки и удаления - на первом проходе определяются доступные объекты, а на втором происходит сборка мусора и при необходимости - уплотнение. Алгоритм предполагает, что в класс VoidPtr добавлен специальный бит пометки :

1. Снять пометку со всех VoidPtr, отсутствующих в списке свободных указателей.

2. Пометить все VoidPtr с ненулевым счетчиком ссылок; то есть пометить объекты, доступные непосредственно из стека.

Иначе перемещение уже состоялось



1 ... 76 77 78 [ 79 ] 80 81 82

© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки.
Яндекс.Метрика