#ifndef MRT_RWLOCK_H
#define MRT_RWLOCK_H
#include <atomic>
#include <pthread.h>
#include "Log.h"
namespace MapleRuntime {
class RwLock {
public:
void LockRead()
{
int count = lockCount.load(std::memory_order_acquire);
do {
while (count == WRITE_LOCKED) {
sched_yield();
count = lockCount.load(std::memory_order_acquire);
}
} while (!lockCount.compare_exchange_weak(count, count + 1, std::memory_order_release));
}
void LockWrite()
{
for (int count = 0; !lockCount.compare_exchange_weak(count, WRITE_LOCKED, std::memory_order_release);
count = 0) {
sched_yield();
}
}
bool TryLockWrite()
{
int count = 0;
if (lockCount.compare_exchange_weak(count, WRITE_LOCKED, std::memory_order_release)) {
return true;
}
return false;
}
bool TryLockRead()
{
int count = lockCount.load(std::memory_order_acquire);
do {
if (count == WRITE_LOCKED) {
return false;
}
} while (!lockCount.compare_exchange_weak(count, count + 1, std::memory_order_release));
return true;
}
void UnlockRead()
{
int count = lockCount.fetch_sub(1);
if (count < 0) {
std::abort();
}
}
void UnlockWrite()
{
CHECK(lockCount.load() == WRITE_LOCKED);
lockCount.store(0, std::memory_order_release);
}
private:
static constexpr int WRITE_LOCKED = -1;
std::atomic<int> lockCount{ 0 };
};
}
#endif