//--------------------------------------------------------------------------- #include #pragma hdrstop //--------------------------------------------------------------------------- #pragma argsused // Программа из конспекта "Системное программное обеспечение" // Взаимные исключения в Windows // стр. ?? // Название: prodcons.c // Описание: Пример задачи писателей-читателя с мьютексами //mutex/prodcons.c #include #include #include #define MAXNITEMS 1000000 #define MAXNTHREADS 100 #define min(a,b) ((a) < (b) ? (a) : (b)) #define max(a,b) ((a) > (b) ? (a) : (b)) static int nitems, potok=0; /* только для чтения потребителем и производителем */ struct { //volatile DWORD int nput, nval; HANDLE mutex; int buff[MAXNITEMS]; } shared = { 0,0}; DWORD WINAPI produce (void *); DWORD WINAPI consume (void *); int main(int argc, char **argv) { int i, nthreads, count[MAXNTHREADS]; DWORD IDThread[MAXNTHREADS]; HANDLE tid_produce[MAXNTHREADS], tid_consume; shared.mutex = CreateMutex (NULL, FALSE, NULL); srand ((DWORD)time(NULL)); /* Создать начальное число для генератора случайных чисел. */ if (argc != 3) { printf("usage: prodcons <#items> <#threads>\n"); exit(-1); } nitems = min(atoi(argv[1]), MAXNITEMS); nthreads = min(atoi(argv[2]), MAXNTHREADS); /* запуск всех потоков-производителей */ for (i = 0; i < nthreads; i++) { count[i] = 0; tid_produce[i]=CreateThread(NULL, 0, produce, &count[i],0,&IDThread[i]); potok++; printf("Producer #%d started\n", IDThread[i]); Sleep(1000*rand()%1); } /* ожидание завершения всех производителей */ for (i = 0; i < nthreads; i++) { WaitForSingleObject (tid_produce[i], INFINITE); //printf("count[%d] = %d\n", i, count[i]); printf("Producer #%lu makes %d elements\n", IDThread[i], count[i]); } /* запуск и ожидание завершения потока-потребителя */ tid_consume=CreateThread(NULL, 0, consume, NULL,0,NULL); WaitForSingleObject (tid_consume, INFINITE); CloseHandle (shared.mutex); printf ("Producer and consumer threads ended.\n"); exit(0); } DWORD WINAPI produce (void *arg) { //sleep(50*rand()%2); for ( ; ; ) { sleep(50*rand()%2); WaitForSingleObject (shared.mutex, INFINITE); if (shared.nput >= nitems) { printf ("Producer #%d said: Buffer Full! Cant add value.\n",GetCurrentThreadId()); ReleaseMutex (shared.mutex); return(NULL); /* массив полный, готово */ } shared.buff[shared.nput] = shared.nval; printf("Producer #%d make element %d with value %d\n",GetCurrentThreadId(),shared.nput,shared.nval); shared.nput++; sleep(50*rand()%2); shared.nval++; sleep(50*rand()%2); ReleaseMutex (shared.mutex); *((int *) arg) += 1; } } DWORD WINAPI consume (void *arg) { int i,c=0; printf("Checking buffer\n"); for (i = 0; i < nitems; i++) { if (shared.buff[i] != i) { printf("wrong buff[%d] = %d\n", i, shared.buff[i]); c++; } } if(!c) printf("All elements good!\n"); return(NULL); }