|
藍森林 http://www.lslnet.com 2006年6月6日 10:18
在網上找的一個有用的讀寫鎖
讀寫鎖,作用:
可以用在對於一個資源要實現多個用戶讀,多個用戶寫的情況下,可以避免同時有多個用戶寫該資源,但是可以有多個用戶同時讀,但是不能在有用戶讀的同時,有用戶寫的情況下:
我在網上找了個實現代碼,大家看看,怎麼樣?(TestClass是我寫的);
// TestMFC.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "vector"
#include "TestMFC.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// The one and only application object
CWinApp theApp;
using namespace std;
#ifndef __MUTEX_READERS_WRITERS
#define __MUTEX_READERS_WRITERS
class CMutexRW
{
protected:
HANDLE m_semReaders;
HANDLE m_semWriters;
int m_nReaders;
public:
CMutexRW() :
m_semReaders(NULL),
m_semWriters(NULL),
m_nReaders(0)
{
// initialize the Readers & Writers variables
m_semReaders = ::CreateSemaphore(NULL, 1, 1, NULL);
m_semWriters = ::CreateSemaphore(NULL, 1, 1, NULL);
m_nReaders = 0;
if (m_semReaders == NULL || m_semWriters == NULL)
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
TRACE( "***** ERROR: CreateSemaphore: %s\n", (LPCTSTR)lpMsgBuf );
LocalFree( lpMsgBuf );
}
};
virtual ~CMutexRW()
{
if (m_semWriters)
VERIFY( ::CloseHandle(m_semWriters) );
m_semWriters = NULL;
if (m_semReaders)
VERIFY( ::CloseHandle(m_semReaders) );
m_semReaders = NULL;
}
inline void Lock_DataRead(){
DWORD dwEvent = WAIT_TIMEOUT;
// P( semReaders )
dwEvent = ::WaitForSingleObject( m_semReaders, INFINITE );
ASSERT(dwEvent == WAIT_OBJECT_0);
m_nReaders++;
if (m_nReaders == 1)
{
// P( semWriters )
dwEvent = ::WaitForSingleObject( m_semWriters, INFINITE );
ASSERT(dwEvent == WAIT_OBJECT_0);
}
// V( semReaders )
VERIFY( ::ReleaseSemaphore( m_semReaders, 1, NULL ) );
};
inline void Unlock_DataRead(){
DWORD dwEvent = WAIT_TIMEOUT;
// P( semReaders )
dwEvent = ::WaitForSingleObject( m_semReaders, INFINITE );
ASSERT(dwEvent == WAIT_OBJECT_0);
m_nReaders--;
if (m_nReaders == 0)
{
// V( semWriters )
VERIFY( ::ReleaseSemaphore(m_semWriters, 1, NULL) );
}
// V( semReaders )
VERIFY( ::ReleaseSemaphore( m_semReaders, 1, NULL ) );
};
inline void Lock_DataWrite(){
DWORD dwEvent = WAIT_TIMEOUT;
// P( semWriters )
dwEvent = ::WaitForSingleObject( m_semWriters, INFINITE );
ASSERT(dwEvent == WAIT_OBJECT_0);
}
inline void Unlock_DataWrite(){
// V( semWriters )
VERIFY( ::ReleaseSemaphore(m_semWriters, 1, NULL) );
};
};
class CReadLock
{
protected:
CMutexRW* m_pMutexRW;
bool m_bIsLocked;
public:
CReadLock(CMutexRW* pMutexRW, const bool bInitialLock = false) :
m_pMutexRW(pMutexRW), m_bIsLocked(false)
{
ASSERT(m_pMutexRW);
if (bInitialLock){
m_pMutexRW->;Lock_DataRead();
m_bIsLocked = true;
}
};
inline const bool& IsLocked() const{
return m_bIsLocked;
};
inline void Lock(){
ASSERT(m_bIsLocked == false);
m_pMutexRW->;Lock_DataRead();
m_bIsLocked = true;
};
inline void Unlock(){
ASSERT(m_bIsLocked);
m_pMutexRW->;Unlock_DataRead();
m_bIsLocked = false;
};
virtual ~CReadLock(){
if (m_bIsLocked){
m_pMutexRW->;Unlock_DataRead();
}
};
};
class CWriteLock
{
protected:
CMutexRW* m_pMutexRW;
bool m_bIsLocked;
public:
CWriteLock(CMutexRW* pMutexRW, const bool bInitialLock = false) :
m_pMutexRW(pMutexRW), m_bIsLocked(false)
{
ASSERT(m_pMutexRW);
if (bInitialLock){
m_pMutexRW->;Lock_DataWrite();
m_bIsLocked = true;
}
};
inline const bool& IsLocked() const{
return m_bIsLocked;
};
inline void Lock(){
ASSERT(m_bIsLocked == false);
m_pMutexRW->;Lock_DataWrite();
m_bIsLocked = true;
};
inline void Unlock(){
ASSERT(m_bIsLocked);
m_pMutexRW->;Unlock_DataWrite();
m_bIsLocked = false;
};
virtual ~CWriteLock(){
if (m_bIsLocked){
m_pMutexRW->;Unlock_DataWrite();
}
};
};
#endif // end #ifndef __MUTEX_READERS_WRITERS
static int ThreadID;
CMutexRW m_Mutex;
class TestClass
{
public:
std::vector<HANDLE>; ThreadArray;
public:
static DWORD WINAPI Thread_Read(LPVOID nParament)
{
int ID= ThreadID;
ThreadID++;
m_Mutex.Lock_DataRead();
for(int i =0 ;i<4;i++)
{
printf("reading:%d\n",ID);
::Sleep(100);
}
m_Mutex.Unlock_DataRead();
return 1;
};
static DWORD WINAPI Thread_Write(LPVOID nParament)
{
int ID = ThreadID;
ThreadID++;
m_Mutex.Lock_DataWrite();
for(int i=0;i<4;i++)
{
printf("writing:%d\n",ID);
::Sleep(100);
}
m_Mutex.Unlock_DataWrite();
return 1;
};
void Test()
{
for(int i=0;i<10;i++)
{
if(i/2 == 1)
{
HANDLE ThreadHandle = ::CreateThread(NULL,0,Thread_Read,0,0,NULL);
ThreadArray.push_back(ThreadHandle);
}
else
{
HANDLE ThreadHandle = ::CreateThread(NULL,0,Thread_Write,0,0,NULL);
ThreadArray.push_back(ThreadHandle);
}
};
};
void About()
{
int i=0;
while(1)
{
::Sleep(100);
HANDLE ThreadHandle = ThreadArray[i];
DWORD ExitCode;
::GetExitCodeThread(ThreadHandle,&ExitCode);
if(ExitCode !=STILL_ACTIVE)
{
i++;
if(i == ThreadArray.size())
return ;
}
else
i=0;
}
}
public:
TestClass(){ThreadID = 0;};
~TestClass(){About();};
};
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
cerr << _T("Fatal Error: MFC initialization failed") << endl;
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
CString strHello;
strHello.LoadString(IDS_HELLO);
cout << (LPCTSTR)strHello << endl;
TestClass m_Test;
m_Test.Test();
}
return nRetCode;
} |
在網上找的一個有用的讀寫鎖
用code對齊
這樣大家看起來都方便
[code]
// TestMFC.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "vector"
#include "TestMFC.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// The one and only application object
CWinApp theApp;
using namespace std;
#ifndef __MUTEX_READERS_WRITERS
#define __MUTEX_READERS_WRITERS
class CMutexRW
{
protected:
HANDLE m_semReaders;
HANDLE m_semWriters;
int m_nReaders;
public:
CMutexRW() :
m_semReaders(NULL),
m_semWriters(NULL),
m_nReaders(0)
{
// initialize the Readers & Writers variables
m_semReaders = ::CreateSemaphore(NULL, 1, 1, NULL);
m_semWriters = ::CreateSemaphore(NULL, 1, 1, NULL);
m_nReaders = 0;
if (m_semReaders == NULL || m_semWriters == NULL)
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
TRACE( "***** ERROR: CreateSemaphore: %s\n", (LPCTSTR)lpMsgBuf );
LocalFree( lpMsgBuf );
}
};
virtual ~CMutexRW()
{
if (m_semWriters)
VERIFY( ::CloseHandle(m_semWriters) );
m_semWriters = NULL;
if (m_semReaders)
VERIFY( ::CloseHandle(m_semReaders) );
m_semReaders = NULL;
}
inline void Lock_DataRead(){
DWORD dwEvent = WAIT_TIMEOUT;
// P( semReaders )
dwEvent = ::WaitForSingleObject( m_semReaders, INFINITE );
ASSERT(dwEvent == WAIT_OBJECT_0);
m_nReaders++;
if (m_nReaders == 1)
{
// P( semWriters )
dwEvent = ::WaitForSingleObject( m_semWriters, INFINITE );
ASSERT(dwEvent == WAIT_OBJECT_0);
}
// V( semReaders )
VERIFY( ::ReleaseSemaphore( m_semReaders, 1, NULL ) );
};
inline void Unlock_DataRead(){
DWORD dwEvent = WAIT_TIMEOUT;
// P( semReaders )
dwEvent = ::WaitForSingleObject( m_semReaders, INFINITE );
ASSERT(dwEvent == WAIT_OBJECT_0);
m_nReaders--;
if (m_nReaders == 0)
{
// V( semWriters )
VERIFY( ::ReleaseSemaphore(m_semWriters, 1, NULL) );
}
// V( semReaders )
VERIFY( ::ReleaseSemaphore( m_semReaders, 1, NULL ) );
};
inline void Lock_DataWrite(){
DWORD dwEvent = WAIT_TIMEOUT;
// P( semWriters )
dwEvent = ::WaitForSingleObject( m_semWriters, INFINITE );
ASSERT(dwEvent == WAIT_OBJECT_0);
}
inline void Unlock_DataWrite(){
// V( semWriters )
VERIFY( ::ReleaseSemaphore(m_semWriters, 1, NULL) );
};
};
class CReadLock
{
protected:
CMutexRW* m_pMutexRW;
bool m_bIsLocked;
public:
CReadLock(CMutexRW* pMutexRW, const bool bInitialLock = false) :
m_pMutexRW(pMutexRW), m_bIsLocked(false)
{
ASSERT(m_pMutexRW);
if (bInitialLock){
m_pMutexRW->;Lock_DataRead();
m_bIsLocked = true;
}
};
inline const bool& IsLocked() const{
return m_bIsLocked;
};
inline void Lock(){
ASSERT(m_bIsLocked == false);
m_pMutexRW->;Lock_DataRead();
m_bIsLocked = true;
};
inline void Unlock(){
ASSERT(m_bIsLocked);
m_pMutexRW->;Unlock_DataRead();
m_bIsLocked = false;
};
virtual ~CReadLock(){
if (m_bIsLocked){
m_pMutexRW->;Unlock_DataRead();
}
};
};
class CWriteLock
{
protected:
CMutexRW* m_pMutexRW;
bool m_bIsLocked;
public:
CWriteLock(CMutexRW* pMutexRW, const bool bInitialLock = false) :
m_pMutexRW(pMutexRW), m_bIsLocked(false)
{
ASSERT(m_pMutexRW);
if (bInitialLock){
m_pMutexRW->;Lock_DataWrite();
m_bIsLocked = true;
}
};
inline const bool& IsLocked() const{
return m_bIsLocked;
};
inline void Lock(){
ASSERT(m_bIsLocked == false);
m_pMutexRW->;Lock_DataWrite();
m_bIsLocked = true;
};
inline void Unlock(){
ASSERT(m_bIsLocked);
m_pMutexRW->;Unlock_DataWrite();
m_bIsLocked = false;
};
virtual ~CWriteLock(){
if (m_bIsLocked){
m_pMutexRW->;Unlock_DataWrite();
}
};
};
#endif // end #ifndef __MUTEX_READERS_WRITERS
static int ThreadID;
CMutexRW m_Mutex;
class TestClass
{
public:
std::vector<HANDLE>; ThreadArray;
public:
static DWORD WINAPI Thread_Read(LPVOID nParament)
{
int ID= ThreadID;
ThreadID++;
m_Mutex.Lock_DataRead();
for(int i =0 ;i<4;i++)
{
printf("reading:%d\n",ID);
::Sleep(100);
}
m_Mutex.Unlock_DataRead();
return 1;
};
static DWORD WINAPI Thread_Write(LPVOID nParament)
{
int ID = ThreadID;
ThreadID++;
m_Mutex.Lock_DataWrite();
for(int i=0;i<4;i++)
{
printf("writing:%d\n",ID);
::Sleep(100);
}
m_Mutex.Unlock_DataWrite();
return 1;
};
void Test()
{
for(int i=0;i<10;i++)
{
if(i/2 == 1)
{
HANDLE ThreadHandle = ::CreateThread(NULL,0,Thread_Read,0,0,NULL);
ThreadArray.push_back(ThreadHandle);
}
else
{
HANDLE ThreadHandle = ::CreateThread(NULL,0,Thread_Write,0,0,NULL);
ThreadArray.push_back(ThreadHandle);
}
};
};
void About()
{
int i=0;
while(1)
{
::Sleep(100);
HANDLE ThreadHandle = ThreadArray[i];
DWORD ExitCode;
::GetExitCodeThread(ThreadHandle,&ExitCode);
if(ExitCode !=STILL_ACTIVE)
{
i++;
if(i == ThreadArray.size())
return ;
}
else
i=0;
}
}
public:
TestClass(){ThreadID = 0;};
~TestClass(){About();};
};
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
int nRetCode = 0;
// initialize MFC and print and error on failure
if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
{
// TODO: change error code to suit your needs
cerr << _T("Fatal Error: MFC initialization failed") << endl;
nRetCode = 1;
}
else
{
// TODO: code your application's behavior here.
CString strHello;
strHello.LoadString(IDS_HELLO);
cout << (LPCTSTR)strHello << endl;
TestClass m_Test;
m_Test.Test();
}
return nRetCode;
}
[/code] |
在網上找的一個有用的讀寫鎖
有 c嗎 |
| |