From d52f02225fd83667435c69be059c80703a864fe0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=A9=BB=E9=AD=82=E5=9C=A3=E4=BD=BF?= Date: Wed, 10 Jul 2024 02:58:42 +0800 Subject: [PATCH] =?UTF-8?q?=E5=BC=95=E5=85=A5=E5=BC=BA=E5=88=B6=E6=89=A7?= =?UTF-8?q?=E8=A1=8C=E7=9A=84=E8=AF=BB=E5=86=99=E9=94=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CMakeLists.txt | 1 + include/mutex/shared_mutex.h | 166 +++++++++++++++++++++++++++++++++++ main.cpp | 45 ++++++++++ src/mutex/shared_mutex.cpp | 10 +++ 4 files changed, 222 insertions(+) create mode 100644 include/mutex/shared_mutex.h create mode 100644 src/mutex/shared_mutex.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 56b766e..a8781fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,6 +7,7 @@ add_library(DataStruct src/RedBlackTree.cpp src/HeapSort.cpp include/HeapSort.h + src/mutex/shared_mutex.cpp ) target_include_directories(DataStruct PUBLIC include) diff --git a/include/mutex/shared_mutex.h b/include/mutex/shared_mutex.h new file mode 100644 index 0000000..1db8829 --- /dev/null +++ b/include/mutex/shared_mutex.h @@ -0,0 +1,166 @@ +// 版权所有 (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(value) { + } + + shared_mutex(const shared_mutex &) = delete; + + shared_mutex &operator=(const shared_mutex &) = delete; + + + 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 + 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; + } + }; + + /// 资源的只读代理 + 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; + } + + + }; + +} // ling + +#endif //DATASTRUCT_SHARED_MUTEX_H_04 diff --git a/main.cpp b/main.cpp index 261b529..72cd8ab 100644 --- a/main.cpp +++ b/main.cpp @@ -5,6 +5,7 @@ #include #include #include +#include class RedBlackTree : public ling::RedBlackTree { protected: @@ -28,6 +29,50 @@ auto duration = std::chrono::duration_cast(__ling_end std::cout << text << ": " << std::fixed << std::setprecision(6) <<((double)duration.count() / 1000000) << " 秒(" << duration.count() <<" 微秒)" << std::endl;\ }while(false) +class mutex_test { +public: + int test() { + return 1; + } + + int test_const() const { + return 2; + } +}; + +TEST(资源管理, 1) { + auto mutex = ling::shared_mutex(mutex_test()); + + auto ptr = std::make_shared(); + { + auto lock = mutex.lock(); + lock->test(); + lock->test_const(); + } + { + auto shared = mutex.lock_shared(); + auto shared2 = mutex.lock_shared(); + shared->test_const(); + shared2->test_const(); + } + { + auto lock = mutex.try_lock(); + ASSERT_TRUE(lock); + auto lock_2 = mutex.try_lock(); + ASSERT_FALSE(lock_2); + auto lock_3 = mutex.try_lock_shared(); + ASSERT_FALSE(lock_3); + } + { + auto lock = mutex.try_lock_shared(); + ASSERT_TRUE(lock); + auto lock_2 = mutex.try_lock(); + ASSERT_FALSE(lock_2); + auto lock_3 = mutex.try_lock_shared(); + ASSERT_TRUE(lock_3); + } +} + TEST(排序, 堆排序测试) { std::random_device rd; diff --git a/src/mutex/shared_mutex.cpp b/src/mutex/shared_mutex.cpp new file mode 100644 index 0000000..15ac3a0 --- /dev/null +++ b/src/mutex/shared_mutex.cpp @@ -0,0 +1,10 @@ +// 版权所有 (c) ling 保留所有权利。 +// 除非另行说明,否则仅允许在DataStruct中使用此文件中的代码。 +// +// 由 ling 创建于 24-7-10. +// + +#include "mutex/shared_mutex.h" + +namespace ling { +} // ling \ No newline at end of file