140 lines
2.4 KiB
C++
140 lines
2.4 KiB
C++
#pragma once
|
|
|
|
#include <mutex>
|
|
#include <atomic>
|
|
|
|
#define MUTEX_ATTRIBUTE_FAST 1
|
|
#define MUTEX_ATTRIBUTE_RECURSIVE 2
|
|
#define MUTEX_ATTRIBUTE_ERRORCHK 3
|
|
|
|
class CriticalSection
|
|
{
|
|
public:
|
|
explicit CriticalSection(int attribute = MUTEX_ATTRIBUTE_FAST)
|
|
: is_recursive(attribute == MUTEX_ATTRIBUTE_RECURSIVE) {}
|
|
|
|
void lock() {
|
|
if (is_recursive) {
|
|
recursive_mutex.lock();
|
|
} else {
|
|
regular_mutex.lock();
|
|
}
|
|
}
|
|
|
|
void unlock() {
|
|
if (is_recursive) {
|
|
recursive_mutex.unlock();
|
|
} else {
|
|
regular_mutex.unlock();
|
|
}
|
|
}
|
|
|
|
bool trylock() {
|
|
return is_recursive ? recursive_mutex.try_lock() : regular_mutex.try_lock();
|
|
}
|
|
|
|
private:
|
|
std::mutex regular_mutex;
|
|
std::recursive_mutex recursive_mutex;
|
|
bool is_recursive;
|
|
};
|
|
|
|
class Mutex
|
|
{
|
|
public:
|
|
Mutex() = default;
|
|
|
|
void lock() { main_mutex.lock(); }
|
|
void unlock() { main_mutex.unlock(); }
|
|
bool trylock() { return main_mutex.try_lock(); }
|
|
|
|
void readlock(const char* = nullptr, int = 0) {
|
|
while (true) {
|
|
std::unique_lock read_lock(read_mutex);
|
|
if (!writing.load()) {
|
|
readers.fetch_add(1);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void releasereadlock(const char* = nullptr, int = 0) {
|
|
readers.fetch_sub(1);
|
|
}
|
|
|
|
bool tryreadlock(const char* = nullptr) {
|
|
std::lock_guard read_lock(read_mutex);
|
|
if (!writing.load()) {
|
|
readers.fetch_add(1);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void writelock(const char* = nullptr, int = 0) {
|
|
write_mutex.lock();
|
|
waitReaders();
|
|
}
|
|
|
|
void releasewritelock(const char* = nullptr, int = 0) {
|
|
writing.store(false);
|
|
write_mutex.unlock();
|
|
}
|
|
|
|
bool trywritelock(const char* = nullptr) {
|
|
if (!write_mutex.try_lock()) return false;
|
|
|
|
if (readers.load() == 0) {
|
|
writing.store(true);
|
|
return true;
|
|
}
|
|
|
|
write_mutex.unlock();
|
|
return false;
|
|
}
|
|
|
|
void waitReaders(const char* = nullptr, int = 0) {
|
|
while (readers.load() > 0) {}
|
|
writing.store(true);
|
|
}
|
|
|
|
void SetName(const std::string&) {}
|
|
|
|
private:
|
|
std::mutex read_mutex;
|
|
std::mutex write_mutex;
|
|
std::mutex main_mutex;
|
|
std::atomic<int> readers{0};
|
|
std::atomic<bool> writing{false};
|
|
};
|
|
|
|
class LockMutex
|
|
{
|
|
public:
|
|
explicit LockMutex(Mutex* mutex, bool lock_immediately = true)
|
|
: mut(mutex), locked(lock_immediately) {
|
|
if (locked) mut->lock();
|
|
}
|
|
|
|
~LockMutex() {
|
|
if (locked) mut->unlock();
|
|
}
|
|
|
|
void unlock() {
|
|
if (locked) {
|
|
mut->unlock();
|
|
locked = false;
|
|
}
|
|
}
|
|
|
|
void lock() {
|
|
if (!locked) {
|
|
mut->lock();
|
|
locked = true;
|
|
}
|
|
}
|
|
|
|
private:
|
|
Mutex* mut;
|
|
bool locked;
|
|
}; |