// 版权所有 (c) ling 保留所有权利。 // 除非另行说明,否则仅允许在DataStruct中使用此文件中的代码。 // // 由 ling 创建于 24-7-10. // #ifndef DATASTRUCT_SHARED_MUTEX_H_04 #define DATASTRUCT_SHARED_MUTEX_H_04 #include namespace ling { template class ResourceReadOnly; template class ResourceCompletely; /// 强制执行的读写锁 /// 当获取共享锁时,返回资源的只读代理 /// 仅在获取独占锁时,才返回资源的完全代理 /// 不管获取哪一个代理,都会在代理被释放时自动解除锁定 template 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 lock_completely = lock(); this->resource = value; } ResourceReadOnly lock_shared() { mutex.lock_shared(); return ResourceReadOnly(&mutex, &resource); } ResourceReadOnly try_lock_shared() { if (mutex.try_lock_shared()) { return ResourceReadOnly(&mutex, &resource); } return ResourceReadOnly(); } ResourceCompletely lock() { mutex.lock(); return ResourceCompletely(&mutex, &resource); } ResourceCompletely try_lock() { if (mutex.try_lock()) { return ResourceCompletely(&mutex, &resource); } return ResourceCompletely(); } }; template ling::shared_mutex make_shared_mutex(Args &&... args) { return ling::shared_mutex(std::move(T(std::forward(args)...))); } template ling::shared_mutex make_shared_mutex(Args &&... args) { return ling::shared_mutex(std::move(T(std::forward(args)...))); } /// 资源的读写代理 template 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 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