163 lines
6.4 KiB
C
163 lines
6.4 KiB
C
//================================================================================
|
|
// Microsoft Confidential
|
|
// Copyright (C) Microsoft 1997
|
|
//
|
|
// Author: RameshV
|
|
//================================================================================
|
|
|
|
|
|
//================================================================================
|
|
// Required Headers
|
|
//================================================================================
|
|
#include <adt.h>
|
|
|
|
//================================================================================
|
|
// 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
|
|
//================================================================================
|