|
Последовательное копирование Функция Swap() вызывается в произвольные моменты и, скорее всего, будет работать в течение некоторого времени. В работе программы возникают непредсказуемые затяжки, а это бесит пользователей едва ли не больше, чем аппаратные сбои. К счастью, алгоритм Бейкера легко модифицировать, чтобы копирование выполнялось поэтапно в фоновом режиме. На мосту Бей-Бридж в Сан-Франциско постоянно работает бригада маляров. Она начинает красить мост с одного конца и через пару лет успешно докрашивает до другого. К этому времени можно начинать красить заново, в другую сторону. Работа идет постоянно, не считая редких перерывов из-за землетрясений или демонстраций протеста. В сущности, именно так алгоритм Бейкера превращается в схему последовательного уплотнения. Начинаем следующий заход на класс Space. Функция Swap() делится на две части, одна из которых переключает активные половины, а другая многократно вызывается и при каждом вызове копирует по одному объекту. class Space { private: VoidPtrIterator* iterator; // Информация о копировании HalfSpace A, B; HalfSpace* active; HalfSpace* inactive; void Swap(); // Переключить активную половину, скопировать объекты public: Space() : active(&A), inactive(&B), iterator(NULL) { Swap(); } void* Allocate(size_t size); void Copy1(); }; void* Space::Allocate(size_t size) { void* 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(); delete iterator; iterator = VoidPtr::pool->iterator(); } void Space::Copy1() { if (!iterator->More()) Swap(); // Начать работу в другую сторону else { VoidPtr* vp = iterator->Next(); if (vp->address >= inactive && vp->address < inactive + sizeof(*inactive)) { void* new_space = active->Allocate(size); if (new_space == NULL) throw(OutOfMemory()); memcpy(new_space, vp->address, vp->size); vp->address = new_space; } } } Функцию Copy1() необходимо вызывать как можно чаще, однако делать это можно в ходе нормальной работы программы. Новые объекты размещаются в активной половине, смешиваются со скопированными объектами, но это не приносит вреда. Поскольку перед копированием мы убеждаемся, что объект в данный момент находится в неактивном пространстве, созданные в активной половине объекты остаются без изменений. |
Copyright 2005. Климов Александр. All Right Reserved.