//*************************************************************** // illustrates two processes cooperating in a producer/consumer relationship // The producer/consumer relationship is managed by two semaphores // EMPTY and FULL, When EMPTY the producer can produce into empty buffer, // when FULL the consumer can consume buffer. // the buffer is passed through shared memory using the file mapping mechanism // This code demonstrates the consumer side // AUTHOR: Chris Wild // DATE: September 10, 1997 //*************************************************************** #include #include #include const int NBUFFERS = 3; // allow 3 buffers for bounded buffer typedef struct{ int bufID; // buffer number int bufValue; // monotonically increasing number } Buffer; void main(int argc, char *argv[]) { HANDLE empty, full; // control bounded buffer access HANDLE mapFileHandle; // used to access the shared Buffer* commonBuffers; // pointer into memory mapped file to array of buffer structures cout << "Entered consumer: v2\n"; empty = OpenSemaphore(SEMAPHORE_ALL_ACCESS,FALSE, "NTcourse.semaphore.empty"); if(empty == NULL) { cout << "Error opening empty: " << GetLastError() << endl; ExitProcess(1); } full = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, "NTcourse.semaphore.full"); if(full == NULL) { cout << "Error opening full: " << GetLastError() << endl; ExitProcess(1); } mapFileHandle = OpenFileMapping(PAGE_READWRITE, FALSE, // child cannot inherit "commonBuffer"); if(mapFileHandle == NULL) { cout << "Error opening commonBuffer: " << GetLastError() << endl; ExitProcess(1); } commonBuffers = (Buffer*) MapViewOfFile(mapFileHandle, FILE_MAP_READ, 0, // High offset 0, // Low offest 0); // 0 for mapping entire file if(commonBuffers == NULL) { cout << "Error mapping file: " << GetLastError() << endl; ExitProcess(1); } // enter a loops consuming some things int bufN = 0; DWORD returnValue; while(true) { // First wait for buffer to be produced cout << "CONSUMER: waiting for full buffer\n"; returnValue = WaitForSingleObject(full, 10000); // wait 10 seconds if( returnValue == WAIT_TIMEOUT) { cout << "Waited too long for producer - assumed died\n"; break; } // Have full buffer - consume it cout << "CONSUMER: emptied buffer: " << commonBuffers[bufN].bufID << " with value: " << commonBuffers[bufN].bufValue << endl; bufN = (bufN+1) % NBUFFERS; ReleaseSemaphore(empty,1,0); // signals empty } CloseHandle(empty); CloseHandle(full); CloseHandle(mapFileHandle); }