Files
DataStruct/include/mutex/shared_mutex.h

187 lines
4.9 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 版权所有 (c) ling 保留所有权利。
// 除非另行说明否则仅允许在DataStruct中使用此文件中的代码。
//
// 由 ling 创建于 24-7-10.
//
#ifndef DATASTRUCT_SHARED_MUTEX_H_04
#define DATASTRUCT_SHARED_MUTEX_H_04
#include <shared_mutex>
namespace ling {
template<typename T>
class ResourceReadOnly;
template<typename T>
class ResourceCompletely;
/// 强制执行的读写锁
/// 当获取共享锁时,返回资源的只读代理
/// 仅在获取独占锁时,才返回资源的完全代理
/// 不管获取哪一个代理,都会在代理被释放时自动解除锁定
template<typename T, typename CT = const T>
class shared_mutex {
private:
std::shared_mutex mutex;
T resource;
public:
explicit shared_mutex(T &&value) : resource(std::move(value)) {
}
explicit shared_mutex() = default;
shared_mutex(const shared_mutex &) = delete;
shared_mutex &operator=(const shared_mutex &) = delete;
void setResource(const T &&value) {
//改变持有的资源之前,先获得独占锁
ResourceCompletely<T> lock_completely = lock();
this->resource = value;
}
ResourceReadOnly<CT> lock_shared() {
mutex.lock_shared();
return ResourceReadOnly<CT>(&mutex, &resource);
}
ResourceReadOnly<CT> try_lock_shared() {
if (mutex.try_lock_shared()) {
return ResourceReadOnly<CT>(&mutex, &resource);
}
return ResourceReadOnly<CT>();
}
ResourceCompletely<T> lock() {
mutex.lock();
return ResourceCompletely<T>(&mutex, &resource);
}
ResourceCompletely<T> try_lock() {
if (mutex.try_lock()) {
return ResourceCompletely<T>(&mutex, &resource);
}
return ResourceCompletely<T>();
}
};
template<typename T, typename... Args>
ling::shared_mutex<T> make_shared_mutex(Args &&... args) {
return ling::shared_mutex<T>(std::move(T(std::forward<Args>(args)...)));
}
template<typename T, typename CT, typename... Args>
ling::shared_mutex<T, CT> make_shared_mutex(Args &&... args) {
return ling::shared_mutex<T, CT>(std::move(T(std::forward<Args>(args)...)));
}
/// 资源的读写代理
template<typename T>
class ResourceCompletely {
private:
std::shared_mutex *mutex;
T *resource;
public:
ResourceCompletely(std::shared_mutex *mutex, T *resource)
: mutex(mutex), resource(resource) {
}
ResourceCompletely()
: mutex(nullptr), resource(nullptr) {
}
ResourceCompletely(const ResourceCompletely &) = delete;
ResourceCompletely(ResourceCompletely &&) = delete;
ResourceCompletely &operator=(const ResourceCompletely &) = delete;
ResourceCompletely &operator=(ResourceCompletely &&) = delete;
~ResourceCompletely() {
if (mutex != nullptr)
mutex->unlock();
}
void unlock() {
mutex->unlock();
mutex = nullptr;
resource = nullptr;
}
[[nodiscard]] bool isResource() const {
return resource != nullptr;
}
explicit operator bool() const noexcept {
return isResource();
}
T *operator->() {
return resource;
}
bool operator==(const T *const value) {
return this->resource == value;
}
};
/// 资源的只读代理
template<typename T>
class ResourceReadOnly {
private:
std::shared_mutex *mutex;
T *resource;
public:
ResourceReadOnly(std::shared_mutex *mutex, const T *const resource)
: mutex(mutex), resource(resource) {
}
ResourceReadOnly()
: mutex(nullptr), resource(nullptr) {
}
ResourceReadOnly(const ResourceReadOnly &) = delete;
ResourceReadOnly(ResourceReadOnly &&) = delete;
ResourceReadOnly &operator=(const ResourceReadOnly &) = delete;
ResourceReadOnly &operator=(ResourceReadOnly &&) = delete;
~ResourceReadOnly() {
if (mutex != nullptr)
mutex->unlock_shared();
}
void unlock_shared() {
mutex->unlock_shared();
mutex = nullptr;
resource = nullptr;
}
[[nodiscard]] bool isResource() const {
return resource != nullptr;
}
explicit operator bool() const noexcept {
return isResource();
}
const T *operator->() const {
return resource;
}
bool operator==(const T *const value) {
return this->resource == value;
}
};
} // ling
#endif //DATASTRUCT_SHARED_MUTEX_H_04