|
Программирование >> Формирование пользовательского контейнера
wsprintf(str, Thread 2: loop # %5d , i); hdc = GetDC( (HWND) param) ; TextOut(hdc, 1, 20, str, Istrlen(str)); ReleaseDC((HWND) param, hdc); return 0; } Профамма (см. листинг 3.2) требует включения заголовочного файла thrdapp.h, содержимое которого приведено далее. #define IDM THREAD 100 #define IDH HELP 101 #define IDM PANEL 102 #define IDM EXIT 103 Кроме того, ей нужен следующий файл ресурса: #include <windows.h> #include thrdapp.h ftinclude tcp.rc ThreadAppMenu MENU { POPUP &Threads { MENUITEM &Start Threads\tF2 , IDM THREAD MENUITEM &Control Panels\tF3 , IDM PANEL MENUITEM E&xit\tCtrl+X , IDM EXIT MENUITEM &Help , IDM HELP ThreadAppMenu ACCELERATORS { VK F1, IDM HELP, VIRTKEY VK F2, IMt.THREAD. VIRTKEY VK F3, IDH.PANEL, VIRTKEY X , IDH.EXIT (\/ногопоточный сборщик мусора Хотя управление потоками с помощью панели управления очень полезно При разработке многопоточных программ, применение потоков в этих приложениях гораздо важнее. Оставшаяся часть главы посвящена многопоточной версии сборщика мусора из главы 2, использующего класс GCPtr. Напоминаю, что описанный в предыдущей главе сборщик мусора очищал неиспользуемую память каждый раз, когда объект типа ccptr выходил за пределы области видимости. Хотя такой подход хорош для некоторых приложений, часто лучше запускать сборщик мусора как фоновую задачу, выполняющую очистку динамической памяти при наличии свободных циклов процессора. Реализация, предлагаемая в этой главе, разработана для операционной системы Windows, но основные технические приемы подойдут и для других систем, поддерживающих многопоточность. Преобразовать однопоточный сборщик мусора в многопоточную задачу действительно необыкновенно легко, но это потребует внесения некоторых изменений. Перечислим главные их них. 1. В класс GCPtr следует добавить переменные-члены для сопровождения потока. К их числу относятся: дескриптор потока, дескриптор мьютекса и счетчик экземпляров, который отслеживает количество существующих объектов GCPtr. 2. Конструктор объекта GCPtr должен инициировать поток сбора мусора. Кроме того, конструктор должен создавать мьютекс, обеспечивающий синхронизацию. Это должно происходить только один раз, при создании первого объекта типа GCPtr. 3. Следует определить новое исключение для индикации превышения заданного времени ожидания. 4. Из деструктора объекта GCPtr нужно исключить вызов функции collect (), так как сбор мусора выполняется в специальном потоке. 5. Необходимо описать функцию дсо, служащую в сборщике мусора точкой входа потока. - Должна быть определена функция isRunningO, которая возвращает true, если выполняется сбор мусора. 7. Функции-члены класса GCPtr, обеспечивающие доступ к списку сбора мусора, следует синхронизировать так, чтобы в любой момент времени только один поток обращался к этому списку. В следующих разделах перечисленные изменения описаны подробно. Дополнительные переменные-члены Многопоточная версия сборщика мусора ссрсг требует включения следую, щих переменных-членов: Переменные-члены, поддерживающие многопоточность. unsigned tid; Идентификатор (id) потока static HANDLE hThrd; дескриптор потока static HANDLE hMutex; дескриптор мьютекса static int instCount; счетчик объектов GCPtr Идентификатор потока, используемый сборщиком мусора, хранится в переменной tid. Она требуется при вызове функции beginthreadex (). Дескриптор потока содержится в переменной hThrd. Дескриптор мьютекса, необходимого для синхронизации доступа к объекту GCPtr, запоминается в переменной hMutex. Счетчик существующих объектов типа GCPtr хранится в переменной instcount. Последние три переменные описаны как статические (static), так как они используются всеми экземплярами GCPtr. Далее приведен фрагмент задания их значений вне тела класса GCPtr. tenplate <class Т, int size> int GCPtr<T, size>::instCount = 0; tenplate <class T, int size> HANDLE GCPtr<T, size>::hMutex = 0; tenplate <class T, int size> HANDLE GCPtr<T, size>::hThrd = 0; Многопоточный конструктор объекта GCPtr Помимо своих первоначальных обязанностей многопоточный конструктор GCPtr о должен создавать мьютекс, запускать поток для сбора мусора и обновлять счетчик экземляров. Далее приведена его новая версия. Создает как инициализированные, так и неинициализированные объекты. GCPtr(Т *t=NULL) { Когда создается первый объект, создает также мьютекс и регистрирует функцию shutdovtfnO. if (hMutex==0) { hMutex = CreateMutex{NULL, 0, NULL); atexit(shutdown);
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |