|
|
//+-------------------------------------------------------------------------
//
// Microsoft Windows
//
// Copyright (C) Microsoft Corporation, 1996 - 1999
//
// File: eventlst.cpp
//
// Contents: Microsoft Internet Security Trust Provider
//
// Functions: InitializeListLock
// InitializeListEvent
// LockWaitToWrite
//
// *** local functions ***
// LockInitialize
//
// History: 29-May-1997 pberkman created
//
//--------------------------------------------------------------------------
#include "global.hxx"
#include "eventlst.h"
#define PCB_LIST_DEBUG 0
BOOL LockInitialize(LIST_LOCK *pListLock, DWORD dwDebugMask);
BOOL InitializeListLock(LIST_LOCK *psListLock, DWORD dwDebugMask) { return(LockInitialize(psListLock, dwDebugMask)); }
BOOL InitializeListEvent(HANDLE *phListEvent) { if (!(*phListEvent = CreateEvent(NULL, TRUE, TRUE, NULL))) { return(FALSE); } return(TRUE); }
BOOL EventFree(HANDLE hListEvent) { if ((hListEvent) && (hListEvent != INVALID_HANDLE_VALUE)) { CloseHandle(hListEvent); return(TRUE); }
return(FALSE); }
BOOL LockInitialize(LIST_LOCK *pListLock, DWORD dwDebugMask) { //
// Initialize the variable that indicates the number of
// reader threads that are reading.
// Initially no reader threads are reading.
//
pListLock->dwDebugMask = dwDebugMask;
pListLock->NumReaders = 0;
pListLock->hMutexNoWriter = CreateMutex(NULL, FALSE, NULL);
if (!(pListLock->hMutexNoWriter)) { return(FALSE); }
//
// Create the manual-reset event that is signalled when
// no reader threads are reading. Initially no reader
// threads are reading.
//
pListLock->hEventNoReaders = CreateEvent(NULL, TRUE, TRUE, NULL);
if (pListLock->hEventNoReaders) { return(TRUE); } else { CloseHandle(pListLock->hMutexNoWriter);
pListLock->hMutexNoWriter = NULL;
return(FALSE); } }
BOOL LockFree(LIST_LOCK *pListLock) { if (pListLock->hEventNoReaders) { CloseHandle(pListLock->hEventNoReaders); pListLock->hEventNoReaders = NULL; }
if (pListLock->hMutexNoWriter) { CloseHandle(pListLock->hMutexNoWriter); pListLock->hMutexNoWriter = NULL; }
return(TRUE); }
void LockWaitToWrite(LIST_LOCK *pListLock) { //
// We can write if the following are true:
//
// 1. The mutex guard is available and no
// other threads are writing.
//
// 2. No threads are reading.
//
// Note that, unlike an rtl resource, this attempt
// to write does not lock out other readers. We
// just have to wait patiently for our turn.
//
HANDLE ahObjects[2];
ahObjects[0] = pListLock->hMutexNoWriter; ahObjects[1] = pListLock->hEventNoReaders;
WaitForMultipleObjects(2, ahObjects, TRUE, INFINITE);
# if (DBG) && (PCB_LIST_DEBUG)
DbgPrintf(pListLock->dwDebugMask, "Write Acquire: t:%04lX w:%p r:%p\n", GetCurrentThreadId(), ahObjects[0], ahObjects[1]);
# endif
//
// Exit with the mutex, so as to prevent any more readers or writers
// from coming in.
//
}
void LockDoneWriting(LIST_LOCK *pListLock) { //
// We're done writing, release the mutex so that
// readers or other writers may come in.
//
# if (DBG) && (PCB_LIST_DEBUG)
DbgPrintf(pListLock->dwDebugMask, "Write Release: t:%04lX w:%p r:%p\n", GetCurrentThreadId(), pListLock->hMutexNoWriter, pListLock->hEventNoReaders);
# endif
ReleaseMutex(pListLock->hMutexNoWriter); }
void LockWaitToRead(LIST_LOCK *pListLock) { //
// Acquire the mutex that protects the list data.
//
WaitForSingleObject(pListLock->hMutexNoWriter, INFINITE);
# if (DBG) && (PCB_LIST_DEBUG)
DbgPrintf(pListLock->dwDebugMask, "Read Acquire: t:%04lX w:%p r:%p\n", GetCurrentThreadId(), pListLock->hMutexNoWriter, pListLock->hEventNoReaders);
# endif
//
// Now that we have the mutex, we can modify list data without
// fear of corrupting anyone.
//
//
// Increment the number of reader threads.
//
if (++pListLock->NumReaders == 1) { //
// If this is the first reader thread, set our event to
// reflect this. This is so that anyone waiting to write
// will block until we're done.
//
ResetEvent(pListLock->hEventNoReaders); }
//
// Allow other writer/reader threads to use
// the lock object.
//
ReleaseMutex(pListLock->hMutexNoWriter); }
void LockDoneReading(LIST_LOCK *pListLock) { //
// Acquire the mutex that guards the list data so we can
// decrement the number of readers safely.
//
WaitForSingleObject(pListLock->hMutexNoWriter, INFINITE);
# if (DBG) && (PCB_LIST_DEBUG)
DbgPrintf(pListLock->dwDebugMask, "Read Release: t:%04lX w:%p r:%p\n", GetCurrentThreadId(), pListLock->hMutexNoWriter, pListLock->hEventNoReaders);
# endif
if (--pListLock->NumReaders == 0) { //
// We were the last reader. Wake up any potential
// writers.
//
SetEvent(pListLock->hEventNoReaders); }
//
// Allow other writer/reader threads to use
// the lock object.
//
ReleaseMutex(pListLock->hMutexNoWriter); }
|