242 lines
4.9 KiB
C
242 lines
4.9 KiB
C
/*++
|
|
|
|
Copyright (c) 2001 Microsoft Corporation
|
|
|
|
|
|
Module Name:
|
|
|
|
mrswlock.c
|
|
|
|
Abstract:
|
|
|
|
This module contains multiple readers / single writer implementation.
|
|
|
|
Author:
|
|
|
|
abhisheV 18-October-2001
|
|
|
|
Environment
|
|
|
|
User Level: Win32
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
|
|
|
|
#include "precomp.h"
|
|
|
|
|
|
DWORD
|
|
InitializeRWLock(
|
|
PWZC_RW_LOCK pWZCRWLock
|
|
)
|
|
{
|
|
DWORD dwError = 0;
|
|
SECURITY_ATTRIBUTES SecurityAttributes;
|
|
|
|
|
|
memset(pWZCRWLock, 0, sizeof(WZC_RW_LOCK));
|
|
|
|
__try {
|
|
InitializeCriticalSection(&(pWZCRWLock->csExclusive));
|
|
pWZCRWLock->bInitExclusive = TRUE;
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER) {
|
|
dwError = GetExceptionCode();
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
|
|
__try {
|
|
InitializeCriticalSection(&(pWZCRWLock->csShared));
|
|
pWZCRWLock->bInitShared = TRUE;
|
|
}
|
|
__except (EXCEPTION_EXECUTE_HANDLER) {
|
|
dwError = GetExceptionCode();
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
|
|
memset(&SecurityAttributes, 0, sizeof(SECURITY_ATTRIBUTES));
|
|
|
|
SecurityAttributes.nLength = sizeof(SecurityAttributes);
|
|
SecurityAttributes.lpSecurityDescriptor = NULL;
|
|
SecurityAttributes.bInheritHandle = TRUE;
|
|
|
|
pWZCRWLock->hReadDone = CreateEvent(
|
|
&SecurityAttributes,
|
|
TRUE,
|
|
FALSE,
|
|
NULL
|
|
);
|
|
if (!pWZCRWLock->hReadDone) {
|
|
dwError = GetLastError();
|
|
BAIL_ON_WIN32_ERROR(dwError);
|
|
}
|
|
|
|
SetEvent(pWZCRWLock->hReadDone);
|
|
|
|
return (dwError);
|
|
|
|
error:
|
|
|
|
DestroyRWLock(pWZCRWLock);
|
|
|
|
return (dwError);
|
|
}
|
|
|
|
|
|
VOID
|
|
DestroyRWLock(
|
|
PWZC_RW_LOCK pWZCRWLock
|
|
)
|
|
{
|
|
if (pWZCRWLock->hReadDone) {
|
|
CloseHandle(pWZCRWLock->hReadDone);
|
|
}
|
|
|
|
if (pWZCRWLock->bInitShared == TRUE) {
|
|
DeleteCriticalSection(&(pWZCRWLock->csShared));
|
|
pWZCRWLock->bInitShared = FALSE;
|
|
}
|
|
|
|
if (pWZCRWLock->bInitExclusive == TRUE) {
|
|
DeleteCriticalSection(&(pWZCRWLock->csExclusive));
|
|
pWZCRWLock->bInitExclusive = FALSE;
|
|
}
|
|
|
|
memset(pWZCRWLock, 0, sizeof(WZC_RW_LOCK));
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
VOID
|
|
AcquireSharedLock(
|
|
PWZC_RW_LOCK pWZCRWLock
|
|
)
|
|
{
|
|
//
|
|
// Claim the exclusive critical section. This call blocks if there's
|
|
// an active writer or if there's a writer waiting for active readers
|
|
// to complete.
|
|
//
|
|
|
|
EnterCriticalSection(&(pWZCRWLock->csExclusive));
|
|
|
|
//
|
|
// Claim access to the reader count. If this blocks, it's only for a
|
|
// brief moment while other reader threads go through to increment or
|
|
// decrement the reader count.
|
|
//
|
|
|
|
EnterCriticalSection(&(pWZCRWLock->csShared));
|
|
|
|
//
|
|
// Increment the reader count. If this is the first reader then reset
|
|
// the read done event so that the next writer blocks.
|
|
//
|
|
|
|
if ((pWZCRWLock->lReaders)++ == 0) {
|
|
ResetEvent(pWZCRWLock->hReadDone);
|
|
}
|
|
|
|
//
|
|
// Release access to the reader count.
|
|
//
|
|
|
|
LeaveCriticalSection(&(pWZCRWLock->csShared));
|
|
|
|
//
|
|
// Release access to the exclusive critical section. This enables
|
|
// other readers to come through and the next write to wait for
|
|
// active readers to complete which in turn prevents new readers
|
|
// from entering.
|
|
//
|
|
|
|
LeaveCriticalSection(&(pWZCRWLock->csExclusive));
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
VOID
|
|
AcquireExclusiveLock(
|
|
PWZC_RW_LOCK pWZCRWLock
|
|
)
|
|
{
|
|
DWORD dwStatus = 0;
|
|
|
|
|
|
//
|
|
// Claim the exclusive critical section. This not only prevents other
|
|
// threads from claiming the write lock, but also prevents any new
|
|
// threads from claiming the read lock.
|
|
//
|
|
|
|
EnterCriticalSection(&(pWZCRWLock->csExclusive));
|
|
|
|
pWZCRWLock->dwCurExclusiveOwnerThreadId = GetCurrentThreadId();
|
|
|
|
//
|
|
// Wait for the active readers to release their read locks.
|
|
//
|
|
|
|
dwStatus = WaitForSingleObject(pWZCRWLock->hReadDone, INFINITE);
|
|
|
|
ASSERT(dwStatus == WAIT_OBJECT_0);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
VOID
|
|
ReleaseSharedLock(
|
|
PWZC_RW_LOCK pWZCRWLock
|
|
)
|
|
{
|
|
//
|
|
// Claim access to the reader count. If this blocks, it's only for a
|
|
// brief moment while other reader threads go through to increment or
|
|
// decrement the reader count.
|
|
//
|
|
|
|
EnterCriticalSection(&(pWZCRWLock->csShared));
|
|
|
|
//
|
|
// Decrement the reader count. If this is the last reader, set read
|
|
// done event, which allows the first waiting writer to proceed.
|
|
//
|
|
|
|
if (--(pWZCRWLock->lReaders) == 0) {
|
|
SetEvent(pWZCRWLock->hReadDone);
|
|
}
|
|
|
|
//
|
|
// Release access to the reader count.
|
|
//
|
|
|
|
LeaveCriticalSection(&(pWZCRWLock->csShared));
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
VOID
|
|
ReleaseExclusiveLock(
|
|
PWZC_RW_LOCK pWZCRWLock
|
|
)
|
|
{
|
|
//
|
|
// Make the exclusive critical section available to one other writer
|
|
// or to the first reader.
|
|
//
|
|
|
|
pWZCRWLock->dwCurExclusiveOwnerThreadId = 0;
|
|
|
|
LeaveCriticalSection(&(pWZCRWLock->csExclusive));
|
|
|
|
return;
|
|
}
|
|
|