#include <stdio.h>
#include <assert.h>
#include <windows.h>
#define LOCK_READ 0
#define LOCK_WRITE 1
class rwlock{
public:
rwlock();
~rwlock();
public:
void lock(int direct);
void unlock(int direct);
void lock_exclusive(void);
void unlock_exclusive(void);
void wrlock() { lock(LOCK_WRITE); }
void wrunlock() { unlock(LOCK_WRITE); }
void rdlock() { lock(LOCK_READ); }
void rdunlock() { unlock(LOCK_READ); }
private:
volatile LONG count;
volatile LONG direct;
HANDLE finish_event;
CRITICAL_SECTION start_lock;
};
rwlock::rwlock()
{
count = 0;
direct = 0;
finish_event = CreateEvent(NULL, FALSE, FALSE, NULL);
InitializeCriticalSection(&start_lock);
}
rwlock::~rwlock()
{
assert(count == 0);
CloseHandle(finish_event);
DeleteCriticalSection(&start_lock);
}
void rwlock::lock(int _direct)
{
EnterCriticalSection(&start_lock);
while (count > 0 &&
direct != _direct) {
WaitForSingleObject(finish_event, INFINITE);
}
direct = _direct;
InterlockedIncrement(&count);
LeaveCriticalSection(&start_lock);
}
void rwlock::unlock(int _direct)
{
assert(count > 0);
assert(direct == _direct);
InterlockedDecrement(&count);
SetEvent(finish_event);
}
void rwlock::lock_exclusive(void)
{
EnterCriticalSection(&start_lock);
while (count > 0 &&
direct != _direct) {
WaitForSingleObject(finish_event, INFINITE);
}
InterlockedIncrement(&count);
}
void unlock_exclusive(void)
{
InterlockedDecrement(&count);
LeaveCriticalSection(&start_lock);
}
static DWORD CALLBACK ReadFunc(LPVOID lpVoid)
{
rwlock * plock = (rwlock *)lpVoid;
while ( 1 ) {
plock->rdlock();
printf("Start Read: threaid %x\n", GetCurrentThreadId());
printf("Call Read: threaid %x\n", GetCurrentThreadId());
printf("End Read: threaid %x\n", GetCurrentThreadId());
plock->rdunlock();
}
return 0;
}
int main(int argc, char * argv[])
{
DWORD id;
rwlock lock;
for (int i = 0; i < 10; i ++) {
HANDLE handle = CreateThread(NULL, 0, ReadFunc, &lock, 0, &id);
CloseHandle(handle);
}
while ( 1 ) {
lock.wrlock();
printf("Start Write: threaid %x\n", GetCurrentThreadId());
for (int j = 0; j < 10; j++) {
printf("Call Write: threaid %x\n", GetCurrentThreadId());
}
printf("End Write: threaid %x\n", GetCurrentThreadId());
lock.wrunlock();
}
return 0;
}
|