Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

612 lines
12 KiB

/*++
Copyright (c) 1999-2000 Microsoft Corporation
Module Name:
locks.h
Abstract:
Various C++ class for sync. object
Author:
HueiWang 2/17/2000
--*/
#ifndef __LOCKS_H
#define __LOCKS_H
#include <windows.h>
#include <winbase.h>
#include "assert.h"
#define ARRAY_COUNT(a) sizeof(a) / sizeof(a[0])
//
// Semaphore template
//
template <int init_count, int max_count>
class CTSemaphore
{
private:
HANDLE m_semaphore;
public:
CTSemaphore() : m_semaphore(NULL)
{
m_semaphore = CreateSemaphore(
NULL,
init_count,
max_count,
NULL
);
assert(m_semaphore != NULL);
}
~CTSemaphore()
{
if(m_semaphore)
{
CloseHandle(m_semaphore);
}
}
DWORD
Acquire(
int WaitTime=INFINITE,
BOOL bAlertable=FALSE
)
/*++
--*/
{
return WaitForSingleObjectEx(
m_semaphore,
WaitTime,
bAlertable
);
}
BOOL
AcquireEx(
HANDLE hHandle,
int dwWaitTime=INFINITE,
BOOL bAlertable=FALSE
)
/*++
--*/
{
BOOL bSuccess = TRUE;
DWORD dwStatus;
HANDLE hHandles[] = {m_semaphore, hHandle};
if(hHandle == NULL || hHandle == INVALID_HANDLE_VALUE)
{
SetLastError(ERROR_INVALID_PARAMETER);
bSuccess = FALSE;
}
else
{
dwStatus = WaitForMultipleObjectsEx(
sizeof(hHandles)/sizeof(hHandles[0]),
hHandles,
FALSE,
dwWaitTime,
bAlertable
);
if(dwStatus != WAIT_OBJECT_0)
{
bSuccess = FALSE;
}
}
return bSuccess;
}
BOOL Release(long count=1)
{
return ReleaseSemaphore(m_semaphore, count, NULL);
}
BOOL IsGood()
{
return m_semaphore != NULL;
}
};
//
// Critical section C++ class.
//
class CCriticalSection
{
CRITICAL_SECTION m_CS;
BOOL m_bGood;
public:
CCriticalSection(
DWORD dwSpinCount = 4000 // see InitializeCriticalSection...
) : m_bGood(TRUE)
{
__try {
InitializeCriticalSectionAndSpinCount(&m_CS, dwSpinCount);
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
SetLastError(GetExceptionCode());
m_bGood = FALSE;
}
}
~CCriticalSection()
{
if(IsGood() == TRUE)
{
DeleteCriticalSection(&m_CS);
m_bGood = FALSE;
}
}
BOOL
IsGood()
{
return m_bGood;
}
void Lock()
{
EnterCriticalSection(&m_CS);
}
void UnLock()
{
LeaveCriticalSection(&m_CS);
}
BOOL TryLock()
{
return TryEnterCriticalSection(&m_CS);
}
};
//
// Critical section locker, this class lock the critical section
// at object constructor and release object at destructor, purpose is to
// prevent forgoting to release a critical section.
//
// usage is
//
// void
// Foo( void )
// {
// CCriticalSectionLocker l( <some CCriticalSection instance> )
//
// }
//
//
class CCriticalSectionLocker
{
private:
CCriticalSection& m_cs;
public:
CCriticalSectionLocker( CCriticalSection& m ) : m_cs(m)
{
m.Lock();
}
~CCriticalSectionLocker()
{
m_cs.UnLock();
}
};
//
// Safe counter class.
//
class CSafeCounter
{
private:
long m_Counter;
public:
CSafeCounter(
long init_value=0
) :
m_Counter(init_value)
/*++
--*/
{
}
~CSafeCounter()
{
}
operator+=(long dwValue)
{
long dwNewValue;
dwNewValue = InterlockedExchangeAdd(
&m_Counter,
dwValue
);
return dwNewValue += dwValue;
}
operator-=(long dwValue)
{
long dwNewValue;
dwNewValue = InterlockedExchangeAdd(
&m_Counter,
-dwValue
);
return dwNewValue -= dwValue;
}
operator++()
{
return InterlockedIncrement(&m_Counter);
}
operator++(int)
{
long lValue;
lValue = InterlockedIncrement(&m_Counter);
return --lValue;
}
operator--()
{
return InterlockedDecrement(&m_Counter);
}
operator--(int)
{
long lValue;
lValue = InterlockedDecrement(&m_Counter);
return ++lValue;
}
operator long()
{
return InterlockedExchange(&m_Counter, m_Counter);
}
operator=(const long dwValue)
{
InterlockedExchange(&m_Counter, dwValue);
return dwValue;
}
};
//-------------------------------------------------------------------------
//
// Reader/Writer lock, modified from MSDN
//
typedef enum {
WRITER_LOCK,
READER_LOCK,
NO_LOCK
} RWLOCK_TYPE;
class CRWLock
{
private:
HANDLE hMutex;
HANDLE hWriterMutex;
HANDLE hReaderEvent;
long iReadCount;
long iWriteCount;
long iReadEntry;
long iWriteEntry;
public:
CRWLock()
{
BOOL bSuccess=Init();
assert(bSuccess == TRUE);
}
~CRWLock()
{
Cleanup();
}
//-----------------------------------------------------------
BOOL
Init()
{
hReaderEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
hMutex = CreateEvent(NULL,FALSE,TRUE,NULL);
hWriterMutex = CreateMutex(NULL,FALSE,NULL);
if(!hReaderEvent || !hMutex || !hWriterMutex)
return FALSE;
iReadCount = -1;
iWriteCount = -1;
iReadEntry = 0;
iWriteEntry = 0;
return (TRUE);
}
//-----------------------------------------------------------
void
Cleanup()
{
CloseHandle(hReaderEvent);
CloseHandle(hMutex);
CloseHandle(hWriterMutex);
iReadCount = -1;
iWriteCount = -1;
iReadEntry = 0;
iWriteEntry = 0;
}
//-----------------------------------------------------------
void
Acquire(
RWLOCK_TYPE lockType
)
/*++
++*/
{
if (lockType == WRITER_LOCK)
{
InterlockedIncrement(&iWriteCount);
WaitForSingleObject(hWriterMutex,INFINITE);
WaitForSingleObject(hMutex, INFINITE);
assert(InterlockedIncrement(&iWriteEntry) == 1);
assert(InterlockedExchange(&iReadEntry, iReadEntry) == 0);
}
else
{
if (InterlockedIncrement(&iReadCount) == 0)
{
WaitForSingleObject(hMutex, INFINITE);
SetEvent(hReaderEvent);
}
WaitForSingleObject(hReaderEvent,INFINITE);
InterlockedIncrement(&iReadEntry);
assert(InterlockedExchange(&iWriteEntry, iWriteEntry) == 0);
}
}
//-----------------------------------------------------------
void
Release(
RWLOCK_TYPE lockType
)
/*++
++*/
{
if (lockType == WRITER_LOCK)
{
InterlockedDecrement(&iWriteEntry);
InterlockedDecrement(&iWriteCount);
SetEvent(hMutex);
ReleaseMutex(hWriterMutex);
}
else if(lockType == READER_LOCK)
{
InterlockedDecrement(&iReadEntry);
if (InterlockedDecrement(&iReadCount) < 0)
{
ResetEvent(hReaderEvent);
SetEvent(hMutex);
}
}
}
long GetReadCount()
{
return iReadCount+1;
}
long GetWriteCount()
{
return iWriteCount+1;
}
};
//---------------------------------------------------------------------
class CCMutex
{
HANDLE hMutex;
public:
CCMutex() : hMutex(NULL) {
hMutex=CreateMutex(NULL, FALSE, NULL);
}
~CCMutex() {
CloseHandle(hMutex);
}
DWORD
Lock(
DWORD dwWaitTime=INFINITE,
BOOL bAlertable=FALSE
)
/*++
--*/
{
return WaitForSingleObjectEx(
hMutex,
dwWaitTime,
bAlertable
);
}
BOOL
Unlock()
{
return ReleaseMutex(hMutex);
}
};
//---------------------------------------------------------------------------------
class CCEvent
{
BOOL bManual;
HANDLE hEvent;
public:
CCEvent(
BOOL bManual,
BOOL bInitState
) :
hEvent(NULL),
bManual(bManual)
/*++
--*/
{
hEvent=CreateEvent(
NULL,
bManual,
bInitState,
NULL
);
}
~CCEvent()
{
if( NULL != hEvent )
{
CloseHandle(hEvent);
}
}
DWORD
MsgLock(
DWORD dwWaitTime = INFINITE
)
/*++
--*/
{
HANDLE wait_event[1] = {hEvent};
DWORD result ;
MSG msg ;
// The message loop lasts until we get a WM_QUIT message,
// upon which we shall return from the function.
while (TRUE)
{
// block-local variable
// Read all of the messages in this next loop,
// removing each message as we read it.
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
// If it's a quit message, we're out of here.
if (msg.message == WM_QUIT)
{
return WAIT_ABANDONED;
}
// Otherwise, dispatch the message.
DispatchMessage(&msg);
} // End of PeekMessage while loop.
// Wait for any message sent or posted to this queue
// or for one of the passed handles be set to signaled.
result = MsgWaitForMultipleObjects(
1,
wait_event,
TRUE,
dwWaitTime,
QS_ALLINPUT | QS_ALLPOSTMESSAGE | QS_ALLEVENTS
);
// The result tells us the type of event we have.
if (result == WAIT_OBJECT_0 + 1)
{
// New messages have arrived.
// Continue to the top of the always while loop to
// dispatch them and resume waiting.
continue;
}
else
{
break;
} // End of else clause.
} // End of the always while loop.
return result;
}
DWORD
Lock(
DWORD dwWaitTime=INFINITE,
BOOL bAlertable=FALSE
)
/*++
--*/
{
return WaitForSingleObjectEx(
hEvent,
dwWaitTime,
bAlertable
);
}
BOOL
SetEvent()
{
return ::SetEvent(hEvent);
}
BOOL
ResetEvent()
{
return ::ResetEvent(hEvent);
}
BOOL
PulseEvent()
{
return ::PulseEvent(hEvent);
}
BOOL
IsManual()
{
return bManual;
}
};
#endif