Leaked source code of windows server 2003
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.
 
 
 
 
 
 

293 lines
7.3 KiB

/*++
Copyright (C) 1996-2001 Microsoft Corporation
Module Name:
LOCK.H
Abstract:
Generic class for obtaining read and write locks to some resource.
See lock.h for all documentation.
Classes defined:
CLock
History:
a-levn 5-Sept-96 Created.
3/10/97 a-levn Fully documented
--*/
#ifndef __GATEWAY__LOCK__H_
#define __GATEWAY__LOCK__H_
#include <corepol.h>
#include <lockst.h>
#include <statsync.h>
#ifdef DBG
class OperationStat
{
enum { HistoryLength = 122 };
DWORD signature;
DWORD historycData_[HistoryLength];
DWORD historyIndex_;
DWORD opCount_;
DWORD avgTime_;
DWORD maxTime_;
LONG zeroTime_;
public:
static CStaticCritSec lock_;
OperationStat() :
historyIndex_(0), opCount_(0), avgTime_(0), maxTime_(0),signature((DWORD)'nCpO')
{
memset(historycData_, 0, sizeof(historycData_));
};
void addTime(DWORD duration)
{
if (duration==0)
{
InterlockedIncrement(&zeroTime_);
return;
}
if (CStaticCritSec::anyFailure()) return ;
EnterCriticalSection(&lock_);
historycData_[historyIndex_++]=duration;
historyIndex_%=HistoryLength;
if (++opCount_ == 0) ++opCount_;
double avg = (double)avgTime_ + ((double)duration-avgTime_ )/opCount_;
avgTime_ = (DWORD)avg;
if (duration > maxTime_)
{
maxTime_ = duration;
};
LeaveCriticalSection(&lock_);
};
};
extern OperationStat gTimeTraceReadLock;
extern OperationStat gTimeTraceWriteLock;
extern OperationStat gTimeTraceBackupLock;
class TimeTrace
{
DWORD start_;
public:
TimeTrace( ):
start_(GetTickCount())
{ }
~TimeTrace()
{
gTimeTraceBackupLock.addTime(GetTickCount()-start_);
}
};
#define TIMETRACEBACKUP TimeTrace timeTrace;
#else
#define TIMETRACEBACKUP
#endif
//*****************************************************************************
//
// class CLock
//
// Generic class for obtaining read and write locks to some resource.
// Simultaneous reads are allowed, but no concurrent writes or concurrent
// read and write accesses are.
//
// NOTE: this class is for in-process sinchronization only!
//
// Usage: create an instance of this class and share it among the accessing
// threads. Threads must call member functions of the same instance to
// obtain and release locks.
//
//*****************************************************************************
//
// ReadLock
//
// Use this function to request read access to the resource. Access will be
// granted once no threads are writing on the resource. You must call
// ReadUnlock once you are done reading.
//
// Parameters:
//
// DWORD dwTimeout The number of milliseconds to wait for access.
// If access is still unavailable after this time,
// an error is returned.
// Returns:
//
// NoError On Success
// TimedOut On timeout.
// Failed On system error
//
//*****************************************************************************
//
// ReadUnlock
//
// Use this function to release a read lock on the resource. No check is
// performed to assertain that this thread holds a lock. Unmatched calls to
// ReadUnlock may lead to lock integrity violations!
//
// Returns:
//
// NoError On success
// Failed On system error or unmatched call.
//
//*****************************************************************************
//
// WriteLock
//
// Use this function to request write access to the resource. Access will be
// granted once no threads are reading or writing on the resource. You must
// call WriteUnlock once you are done writing.
//
// Parameters:
//
// DWORD dwTimeout The number of milliseconds to wait for access.
// If access is still unavailable after this time,
// an error is returned.
// Returns:
//
// NoError On Success
// TimedOut On timeout.
// Failed On system error
//
//*****************************************************************************
//
// WriteUnlock
//
// Use this function to release a write lock on the resource. No check is
// performed to assertain that this thread holds a lock. Unmatched calls to
// WriteUnlock may lead to lock integrity violations!
//
// Returns:
//
// NoError On success
// Failed On system error or unmatched call.
//
//*****************************************************************************
//
// DowngradeLock
//
// Use this function to "convert" a Write lock into a Read lock. That is, if
// you are currently holding a write lock and call DowngradeLock, you will
// be holding a read lock with the guarantee that no one wrote anything between
// the unlock and the lock
//
// Returns:
//
// NoError On Success
// Failed On system error or unmatched call
//
//******************************************************************************
class CLock
{
public:
enum { NoError = 0, TimedOut, Failed };
int ReadLock(DWORD dwTimeout = INFINITE);
int ReadUnlock();
int WriteLock(DWORD dwTimeout = INFINITE);
int WriteUnlock();
int DowngradeLock();
CLock();
~CLock();
protected:
int WaitFor(HANDLE hEvent, DWORD dwTimeout);
protected:
int m_nWriting;
int m_nReading;
int m_nWaitingToWrite;
int m_nWaitingToRead;
CriticalSection m_csEntering;
CriticalSection m_csAll;
HANDLE m_hCanWrite;
HANDLE m_hCanRead;
DWORD m_WriterId;
//CFlexArray m_adwReaders;
enum { MaxRegistredReaders = 16,
MaxTraceSize = 7};
DWORD m_dwArrayIndex;
struct {
DWORD ThreadId;
//PVOID Trace[MaxTraceSize];
} m_adwReaders[MaxRegistredReaders];
};
#ifdef DBG
class CAutoReadLock
{
DWORD start;
public:
CAutoReadLock(CLock *lock) : m_lock(lock), m_bLocked(FALSE) { }
~CAutoReadLock() { Unlock(); }
void Unlock() {if ( m_bLocked) { m_lock->ReadUnlock(); m_bLocked = FALSE; gTimeTraceReadLock.addTime(GetTickCount()-start);} }
bool Lock() {if (!m_bLocked) { start = GetTickCount(); return m_bLocked = (CLock::NoError == m_lock->ReadLock()) ; } else {return false;}; }
private:
CLock *m_lock;
BOOL m_bLocked;
};
class CAutoWriteLock
{
DWORD start;
public:
CAutoWriteLock(CLock *lock) : m_lock(lock), m_bLocked(FALSE) { }
~CAutoWriteLock() { Unlock(); }
void Unlock() {if ( m_bLocked) { m_lock->WriteUnlock(); m_bLocked = FALSE; gTimeTraceWriteLock.addTime(GetTickCount()-start);} }
bool Lock() {if (!m_bLocked) { start = GetTickCount(); return m_bLocked = (CLock::NoError == m_lock->WriteLock()); } else { return false; }; }
private:
CLock *m_lock;
BOOL m_bLocked;
};
#else
class CAutoReadLock
{
public:
CAutoReadLock(CLock *lock) : m_lock(lock), m_bLocked(FALSE) { }
~CAutoReadLock() { Unlock(); }
void Unlock() {if ( m_bLocked) { m_lock->ReadUnlock(); m_bLocked = FALSE; } }
bool Lock() {if (!m_bLocked) { return m_bLocked = (CLock::NoError == m_lock->ReadLock()) ; } else {return false;}; }
private:
CLock *m_lock;
BOOL m_bLocked;
};
class CAutoWriteLock
{
public:
CAutoWriteLock(CLock *lock) : m_lock(lock), m_bLocked(FALSE) { }
~CAutoWriteLock() { Unlock(); }
void Unlock() {if ( m_bLocked) { m_lock->WriteUnlock(); m_bLocked = FALSE; } }
bool Lock() {if (!m_bLocked) { return m_bLocked = (CLock::NoError == m_lock->WriteLock()); } else { return false; }; }
private:
CLock *m_lock;
BOOL m_bLocked;
};
#endif
#endif