class CReadWriteLock
{
public:
CReadWriteLock();
~CReadWriteLock();
void ReadLock();
void ReadUnlock();
void WriteLock();
void WriteUnlock();
private:
class CReadWriteLockImpl;
CReadWriteLockImpl* m_read_write_lock_impl;
};
class CReadLockGuard
{
public:
explicit CReadLockGuard(CReadWriteLock& lock)
:m_lock(lock)
{
m_lock.ReadLock();
}
~CReadLockGuard()
{
m_lock.ReadUnlock();
}
private:
CReadLockGuard(const CReadLockGuard& rhs);
CReadLockGuard& operator=(const CReadLockGuard& rhs);
CReadWriteLock& m_lock;
};
class CWriteLockGuard
{
public:
explicit CWriteLockGuard(CReadWriteLock& lock)
: m_lock(lock)
{
m_lock.WriteLock();
}
~CWriteLockGuard()
{
m_lock.WriteUnlock();
}
private:
CWriteLockGuard(const CWriteLockGuard& rhs);
CWriteLockGuard& operator=(const CWriteLockGuard& rhs);
CReadWriteLock& m_lock;
};
#include "cwReadWriteLock.h"
#include <stdint.h>
#ifdef _MSC_VER
#include <windows.h>
#else
#include<unistd.h>
#include <pthread.h>
#endif
class CReadWriteLock::CReadWriteLockImpl
{
#ifdef _MSC_VER
typedef CRITICAL_SECTION rw_lock;
#else
typedef pthread_rwlock_t rw_lock;
#endif
public:
CReadWriteLockImpl();
~CReadWriteLockImpl();
void ReadLock();
void ReadUnlock();
void WriteLock();
void WriteUnlock();
private:
rw_lock m_rw_lock;
#ifdef _MSC_VER
rw_lock m_cs_all_leave;
#endif
long m_reader_count;
};
CReadWriteLock::CReadWriteLockImpl::CReadWriteLockImpl()
: m_reader_count(0)
{
#ifdef _MSC_VER
InitializeCriticalSection(&m_rw_lock);
InitializeCriticalSection(&m_cs_all_leave);
#else
pthread_rwlock_init(&m_rw_lock, nullptr);
#endif
}
CReadWriteLock::CReadWriteLockImpl::~CReadWriteLockImpl()
{
#ifdef _MSC_VER
DeleteCriticalSection(&m_rw_lock);
DeleteCriticalSection(&m_cs_all_leave);
#else
pthread_rwlock_destroy(&m_rw_lock);
#endif
}
void CReadWriteLock::CReadWriteLockImpl::ReadLock()
{
#ifdef _MSC_VER
EnterCriticalSection(&m_rw_lock);
if (InterlockedIncrement(&m_reader_count) == 1)
{
EnterCriticalSection(&m_cs_all_leave);
}
LeaveCriticalSection(&m_rw_lock);
#else
pthread_rwlock_rdlock(&m_rw_lock);
#endif
}
void CReadWriteLock::CReadWriteLockImpl::ReadUnlock()
{
#ifdef _MSC_VER
EnterCriticalSection(&m_rw_lock);
if (InterlockedDecrement(&m_reader_count) == 0)
{
LeaveCriticalSection(&m_cs_all_leave);
}
LeaveCriticalSection(&m_rw_lock);
#else
pthread_rwlock_unlock(&m_rw_lock);
#endif
}
void CReadWriteLock::CReadWriteLockImpl::WriteLock()
{
#ifdef _MSC_VER
EnterCriticalSection(&m_rw_lock);
EnterCriticalSection(&m_cs_all_leave);
#else
pthread_rwlock_wrlock(&m_rw_lock);
#endif
}
void CReadWriteLock::CReadWriteLockImpl::WriteUnlock()
{
#ifdef _MSC_VER
LeaveCriticalSection(&m_rw_lock);
LeaveCriticalSection(&m_cs_all_leave);
#else
pthread_rwlock_unlock(&m_rw_lock);
#endif
}
CReadWriteLock::CReadWriteLock()
: m_read_write_lock_impl(new CReadWriteLockImpl)
{
}
CReadWriteLock::~CReadWriteLock()
{
if (m_read_write_lock_impl)
{
delete m_read_write_lock_impl;
}
m_read_write_lock_impl = nullptr;
}
void CReadWriteLock::ReadLock()
{
if (m_read_write_lock_impl)
{
m_read_write_lock_impl->ReadLock();
}
}
void CReadWriteLock::ReadUnlock()
{
if (m_read_write_lock_impl)
{
m_read_write_lock_impl->ReadUnlock();
}
}
void CReadWriteLock::WriteLock()
{
if (m_read_write_lock_impl)
{
m_read_write_lock_impl->WriteLock();
}
}
void CReadWriteLock::WriteUnlock()
{
if (m_read_write_lock_impl)
{
m_read_write_lock_impl->WriteUnlock();
}
}