//================================================================================ // Microsoft Confidential // Copyright (C) Microsoft 1997 // // Author: RameshV //================================================================================ //================================================================================ // Required Headers //================================================================================ #include //================================================================================ // Definitions of the functions. //================================================================================ DWORD // Win32 Errors InitializeProducerConsumer( // Initialize the pointer OUT PPRODCONS Synch, // The memory must be pre-allocated IN DWORD MaxProducers, // Total # of simultaneous producers IN DWORD MaxConsumers // Totat # of consumers ) { Synch->ProducerSemaphore = Synch->ConsumerSemaphore = NULL; Synch->ProducerSemaphore = CreateSemaphore( (LPSECURITY_ATTRIBUTES)NULL, // No security here MaxProducers, // Initial allowed # of producers MaxProducers, // Max allowed at any time NULL // Unnamed ); if( NULL == Synch->ProducerSemaphore ) return GetLastError(); Synch->ConsumerSemaphore = CreateSemaphore( (LPSECURITY_ATTRIBUTES)NULL, // No security here 0, // Initial allowed # of consumers MaxConsumers, // Max allowed at any time NULL // Unnamed ); if( NULL == Synch->ConsumerSemaphore ) return GetLastError(); Synch->MaxProducers = MaxProducers; Synch->MaxConsumers = MaxConsumers; return ERROR_SUCCESS; } VOID DestroyProducerConsumer( // Destroy and free up resources IN PPRODCONS Synch // The producer consumer object ) { if(Synch->ProducerSemaphore) CloseHandle(Synch->ProducerSemaphore); if(Synch->ConsumerSemaphore) CloseHandle(Synch->ConsumerSemaphore); } //================================================================================ // StartProducerEx is expected to be called before trying to "produce" an // element. If a timeout is specified, then the timeout will act like the // same as in WaitForSingleObjectEx. Also, if the Alertable flag is on, the // wait is altertable. The same thing with StartConsumerEx. //================================================================================ DWORD static _inline // Win32 errors StartProdConsExInternal( // Gen. fn to enter prod/cons code (internal) IN PPRODCONS Synch, // Synchronization object IN DWORD TimeOutMilliSec,// Timeout in milliseconds; 0 ==> polling IN BOOL Alertable, // Is the wait alertable? IN BOOL Producer // Is this call from a producer or consumer? ) { DWORD Status; Status = WaitForSingleObjectEx( Producer? Synch->ProducerSemaphore : Synch->ConsumerSemaphore, TimeOutMilliSec, Alertable ); return Status; } DWORD static _inline // Win32 errors EndProdConsExInternal( // Gen. fn to leave prod/cons code(internal) IN PPRODCONS Synch, // Synchronization object IN BOOL Producer // Is this call from a producer or consumer? ) { BOOL Status; Status = ReleaseSemaphore( Producer? Synch->ConsumerSemaphore : Synch->ProducerSemaphore, 1, // Release one producer/consumer NULL // Dont care about how many are still out there ); if( FALSE == Status ) return GetLastError(); return ERROR_SUCCESS; } //================================================================================ // The exported versions are below. The Ex functions allow specification of // TimeOut and if the wait is alertable. The non-Ex functions have the timeout // as INFINITE and Alertable as FALSE by default. //================================================================================ DWORD // Win32 errors StartProducerEx( // See StartProdConsExInternal IN PPRODCONS Synch, // Syncho. object IN DWORD TimeOutMilliSec,// Timeout for wait in milliseconds IN BOOL Alertable // Is the wait alertable? ) { return StartProdConsExInternal(Synch,TimeOutMilliSec,Alertable,TRUE); } DWORD // Win32 errors StartConsumerEx( // See StartProdConsExInternal IN PPRODCONS Synch, // Syncho. object IN DWORD TimeOutMilliSec,// Timeout for wait in milliseconds IN BOOL Alertable // Is the wait alertable? ) { return StartProdConsExInternal(Synch,TimeOutMilliSec,Alertable,FALSE); } // These are usual versions. Return value is success if we entered. // Alertable wait by default, timeout = infinite. So, can return // WAIT_IO_COMPLETION on success. DWORD // Win32 errors StartProducer( // Wait until a producer can start IN PPRODCONS Synch // The synch object ) { DWORD Status = StartProducerEx(Synch, INFINITE, FALSE); if( WAIT_OBJECT_0 == Status ) return ERROR_SUCCESS; return Status; } DWORD // Win32 errors StartConsumer( // Wait until a consumer can start IN PPRODCONS Synch // The synch object ) { DWORD Status = StartConsumerEx(Synch, INFINITE, FALSE); if( WAIT_OBJECT_0 == Status ) return ERROR_SUCCESS; return Status; } DWORD // Win32 Errors EndProducer( // See EndProdConsExInternal IN PPRODCONS Synch // Synch object ) { return EndProdConsExInternal(Synch, TRUE); } DWORD // Win32 errors EndConsumer( // See EndProdConsExInternal IN PPRODCONS Synch // Synch object ) { return EndProdConsExInternal(Synch, TRUE); } //================================================================================ // End of file //================================================================================