#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; }
|