|
Программирование >> Формирование пользовательского контейнера
гопоточность /23 if (WaitForSingleObject (hMutex, 10000) ==WAIT TIMEOUT) throw TimeOutExc(); list<GCInfo<T> >::iterator p; p = findPtrlnfo(t); Если элемент есть в списке gclist, увел1чивает его счетчик ссылок на единицу. В противном случае добавляет этот элемент в список. if(p != gclist.endO) p->refcount++; наращивает счетчик ссылок else { Создает и запоминает этот элемент. GCInfo<T> gcObj(t, size); gclist.push front(gcObj); , addr = t; arraySize = size; if (size > 0) isArray = true; else isArray = false; Наращивает счетчик экземпляров при создании каждого нового объекта. instCount++; Если поток для сбора мусора не выполняется, запускает его. if(hThrd==0) { hThrd = (HANDLE) beginthreadex(NULL, О, gc, (void *) 0, 0, (unsigned *) &tid); Для некоторых приложений лучше понизить приоритет сборщика мусора, как показано далее: SetThreadPriority(hThrd, THREAD PRIORITY BELOW NORMAL); ReieaseMutex(hMutex); Давайте внимательно проанализаруем код. Если переменная hMutex равна О, следовательно, создается первый объект ccptr, и нет еще ни одного созданного для сбора мусора мьютекса. В этом случае создается мьютекс, и его дескриптор присваивается переменной hMutex. В это же время с помощью вызова функции atexit о регистрируется функция shutdownO, как функция завершения. Обратите особое внимание на то, что в многопоточном сборщике мусора функция shutdown () служит двум цслям. Во-первых, как и в первоначальной версии, она освобождает любую неиспользуемую память, не очищенную из-за наличия циклической ссылки. Во-вторых, когда программа, использующая многопоточный сборщик мусора, завершается, она останавливает выполнение потока сбора мусора. Это означает, что к этому моменту могут еще оставаться неудаленные, динамически размещенные объекты. Это важно, так как у них могут быть деструкторы, которые должны быть вызваны. Поскольку функция shutdown () удаляет все оставшиеся объекты, она уничтожит и их. Далее запрашивается мьютекс с помощью функции waitForsingieObjecto. Ее вызов препятствует одновременному обращению двух потоков к списку gclist. Как только получен мьютекс, выполняется поиск в списке gclist элемента с адресом, соответствующим значению переменной t. Если такой элемент найден, его счетчик ссылок увеличивается на единицу. Если же элемента с адресом, заданным в t, нет, создается новый объект типа ccmfo, содержащий этот адрес, и добавляется в список gclist. Затем счетчик instcount наращивается с помощью операции инкремента. Напоминаю, что instcount инициализируется с нулевым значением. Увеличиваясь на единицу при каждом создании объекта, он позволяет следить за числом существующих объектов. Сборщик мусора будет выполняться до тех пор, пока счетчик экземпляров больше 0. Далее, если дескриптор потока hThrd равен О (как при инициализации), следовательно, нет ни одного потока, созданного для сборщика мусора-В этом случае вызывается функция beginthreadex о для запуска потока-Дескриптор этого потока присваивается переменной hThrd. Вызывается функция потока дс (), которая кратко обсуждается далее. В заключение, освобождается мьютекс и конструктор возвращается в вызывающую программу. Важно отметить, что каждый вызов функции WaitForSingieobjecto должен быть сбалансирован вызовом функии ReleaseMutexO, как ЭТО сделано В конструкторе объекта GCPtr. Сбой пр освобождении мьютекса может создать тупиковую ситуацию. Исключение TimeOutExc j(gic ВЫ, вероятно, заметили, в коде конструктора GCPtrO, описанного в дредыдушем разделе, если мьютекс не может быть получен по истечении 10 с, генерируется исключение TimeOutExc. По правде сказать. Юс- это слишком долго, и в этом случае превышения времени ожидания никогда не произойдет, если только что-нибудь не разрушит планировшик заданий операционной системы. Однако если такое событие все-таки возникнет, в коде вашего приложения можно предусмотреть обработку этого исключения. Описание класса TimeOutExc приведено далее. Генерируется исключение при превышении времени ожидания . исключительного права доступа к hMutex. class TimeOutExc { Добавьте обработку, необходимую вашему приложению. Обратите внимание, что этот класс не содержит членов. Его присутствия, как уникального типа данных, достаточно для целей, преследуемых в этой главе. Конечно, вы можете добавить собственную обработку, если захотите. Многопоточный деструктор GCPfr в отличие от однопоточной версии деструктора класса ccptr, в его многопоточной версии -GCPtrO не вызывается функция collect о. Вместо этого в деструкторе просто уменьшается на единицу счетчик ссылок, связанный с объектом GCPtr, выходяшим за пределы области видимости. Действительный сбор мусора (если таковой су шествует) выполняется потоком сбора мусора. В деструкторе также уменьшается на единицу значение счетчика экземпляров InstCount. Далее приведена многопоточная версия деструктора -GCPtr (). Деструктор для объекта GCPtr. template <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
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |