Создание и тестирование многопоточной программы - часть 2
Первый объект изменяет счетчик nCurStep0, второй - nCurStep1. Когда значение счетчика шагов достигнет заданного числа - nStepsAll, объект завершает свою работу. class living_object { static DWORD WINAPI HelperThreadProc(LPVOID p); public: living_object(); virtual void run() {}; virtual ~living_object() {}; }; extern HANDLE hStart; extern CRITICAL_SECTION cs; extern int total_threads; extern DWORD endTick; living_object::living_object() { DWORD threadID; if(!CreateThread(NULL, 0, HelperThreadProc, (LPVOID)this, 0, &threadID)) printf("GetLastError: %d\n", GetLastError()); } DWORD WINAPI living_object::HelperThreadProc(LPVOID p) { EnterCriticalSection(&cs); total_threads++; LeaveCriticalSection(&cs); WaitForSingleObject(hStart, INFINITE); ((living_object*)p)->run(); EnterCriticalSection(&cs); total_threads--; endTick=GetTickCount(); LeaveCriticalSection(&cs); return 0; } Листинг 2. Код класса базового активного объекта living_object .
Тренер, бегущий рядом с бегунами, имеет следующий код (Листинг 3): #include "living_object.h" class CDat; class PrnCurStep : public living_object { public: PrnCurStep(CDat *d); virtual ~PrnCurStep(); void run(); private: CDat *pCDat; long lTmp0; long lTmp1; }; PrnCurStep::PrnCurStep(CDat *d): living_object() { pCDat = d; lTmp0= lTmp1= 0; } PrnCurStep::~PrnCurStep() { } void PrnCurStep::run() { while (pCDat->nStepsAll != pCDat->nCurStep0) { // printf("%d %d\n", pCDat->nCurStep0, pCDat->nCurStep1); ///* if (lTmp0 != pCDat->nCurStep0 lTmp1 != pCDat->nCurStep1) { printf("%d %d\n", pCDat->nCurStep0, pCDat->nCurStep1); lTmp0 = pCDat->nCurStep0; lTmp1 = pCDat->nCurStep1; } // Sleep(0); //*/ } } Листинг 3. Код класса "тренер".
В рамках метода run "тренер" на каждой итерации цикла выводит на консоль текущие значения счетчика циклов обоих бегунов.
Тестирование. Запустив программу, моделирующую бегунов, мы получим результат, который показан на рис.1.

