Многопоточный деструктор GCPtr |
В отличие от однопоточной версии деструктора класса GCPtr, в его многопоточной версии -GCPtrO не вызывается функция collect о. Вместо этого в деструкторе просто уменьшается на единицу счетчик ссылок, связанный с объектом GCPtr, выходящим за пределы области видимости. Действительный сбор мусора (если таковой существует) выполняется потоком сбора мусора. В деструкторе также уменьшается на единицу значение счетчика экземпляров Instcount. Далее приведена многопоточная версия деструктора -GCPtr (). Ч Деструктор для объекта GCPtr. tenplate <class Т, int size> GCPtr<T, size>: :-GCPtrO { if (WaitForSingleObj ect(hMutex, 10000)==WAIT_TIMEOUT) throw TimeOutExc(); list<GCInfo<T> >::iterator p; P = findPtrlnfo(addr); if(p->refcount) p->refcount—; // операция декремента для refcount II Уменьшает на единицу счетчик экземпляров // при каждом уничтожении объекта. InstCount—; ReleaseMutex(hMutex); } Функция дс() Код функции потока для сборщика мусора, названной дс (), приведен далее. // Точка входа для потока сборщика мусора.• template <class Т, int size> unsigned _stdcall GCPtr<T, size>::gc(void * param) { #ifdef DISPLAY cout « "Garbage collection started.\n"; #endif while(isRunning()) { collect(); } collectO; // собирает мусор перед выходом из функции // Освобождает и устанавливает дескриптор потока таким образом, // чтобы поток сбора, мусора можно было возобновить // при необходимости. CloseHandle(hThrd); hThrd = 0; #ifdef DISPLAY cout « "Garbage collection terminated for " « typeid(T).name() « "\n"; #endif return 0; } Функция gco очень проста: она выполняется, пока идет сбор мусора-Функция isRunning о возвращает true, если instcount больше 0 (т. е. есть потребность в сборе мусора), и false — в противном случае. Внутри цикла неПреРывно вызывается функция collectO. Этот подход годится для демонстрации многопоточного сборщика мусора, но вероятно слишком неэффективен для практического применения. Вы можете поэкспериментировать, вызывая функцию collect о реже, например, только если доступная динамическая память почти иссякла. Можно также попробовать вызывать VVindows API-функцию sleep о после каждого вызова функции collect о. функция sleep о приостанавливает выполняющийся поток на заданное количество мс. Приостановленный таким образом поток не расходует время процессора. Когда функция isRunning о возвращает false, цикл завершается, вызывая, в конечном счете, завершение функции дс (), которое останавливает поток сбора мусора. Из-за многопоточности возможно наличие неудаленного элемента в списке gclist, даже когда функция isRunning о возвращает false. Для обработки подобной ситуации выполняется завершающий вызов функции collect () перед окончанием функции дс (). В заключение, освобождается дескриптор потока с помощью вызова Windows API-функции cioseHandie () и задания для него нулевого значения. Присваивание 0 переменной hThrd позволяет конструктору GCPtr повторно запустить поток, если позднее в программе будут созданы новые объекты типа GCPtr.
|