244 lines
5.5 KiB
C++
244 lines
5.5 KiB
C++
//+-------------------------------------------------------------------------
|
|
//
|
|
// 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);
|
|
}
|
|
|
|
|