struct RwLock {
	Mutex     lock_mutex;
	Mutex     write_mutex;
	Semaphore writer_wait;

	int       readers;
	bool      waiting_writer;

	void EnterRead();
	void LeaveRead();
	void EnterWrite();
	void LeaveWrite();

	RwLock() {
		readers = 0;
		waiting_writer = false;
	}
};

void RwLock::EnterWrite()
{
	LLOG("EnterWrite");
	write_mutex.Enter();
	LLOG("EnterWrite:write_mutex.Enter();");
	lock_mutex.Enter();
	ASSERT(!waiting_writer);
	waiting_writer = true;
	if(readers) {
		LLOG("EnterWrite:if(readers)");
		lock_mutex.Leave();
		writer_wait.Wait();
		lock_mutex.Enter();
		LLOG("EnterWrite:writer_wait.Wait();");
	}
	waiting_writer = false;
	lock_mutex.Leave();
	LLOG(".EnterWrite");
}

void RwLock::LeaveWrite()
{
	LLOG("LeaveWrite");
	lock_mutex.Enter();
	lock_mutex.Leave();
	write_mutex.Leave();
	LLOG(".LeaveWrite");
}

void RwLock::EnterRead()
{
	LLOG("EnterRead");
	write_mutex.Enter();
	lock_mutex.Enter();
	readers++;
	lock_mutex.Leave();
	write_mutex.Leave();
	LLOG(".EnterRead");
}

void RwLock::LeaveRead()
{
	LLOG("LeaveRead");
	lock_mutex.Enter();
	LLOG("LeaveRead:lock_mutex.Enter();");
	if(--readers == 0 && waiting_writer) {
		LLOG("LeaveRead:if(--readers == 0 && writer)");
		ASSERT(readers == 0);
		writer_wait.Release();
		LLOG("LeaveRead:writer_wait.Release();");
	}
	LLOG("LeaveRead:--readers");
	lock_mutex.Leave();
	LLOG(".LeaveRead");
}
