引入强制执行的读写锁
This commit is contained in:
@@ -7,6 +7,7 @@ add_library(DataStruct
|
|||||||
src/RedBlackTree.cpp
|
src/RedBlackTree.cpp
|
||||||
src/HeapSort.cpp
|
src/HeapSort.cpp
|
||||||
include/HeapSort.h
|
include/HeapSort.h
|
||||||
|
src/mutex/shared_mutex.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(DataStruct PUBLIC include)
|
target_include_directories(DataStruct PUBLIC include)
|
||||||
|
|||||||
166
include/mutex/shared_mutex.h
Normal file
166
include/mutex/shared_mutex.h
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
// 版权所有 (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(value) {
|
||||||
|
}
|
||||||
|
|
||||||
|
shared_mutex(const shared_mutex &) = delete;
|
||||||
|
|
||||||
|
shared_mutex &operator=(const shared_mutex &) = delete;
|
||||||
|
|
||||||
|
|
||||||
|
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>
|
||||||
|
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<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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // ling
|
||||||
|
|
||||||
|
#endif //DATASTRUCT_SHARED_MUTEX_H_04
|
||||||
45
main.cpp
45
main.cpp
@@ -5,6 +5,7 @@
|
|||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
#include <mutex/shared_mutex.h>
|
||||||
|
|
||||||
class RedBlackTree : public ling::RedBlackTree<int> {
|
class RedBlackTree : public ling::RedBlackTree<int> {
|
||||||
protected:
|
protected:
|
||||||
@@ -28,6 +29,50 @@ auto duration = std::chrono::duration_cast<std::chrono::microseconds>(__ling_end
|
|||||||
std::cout << text << ": " << std::fixed << std::setprecision(6) <<((double)duration.count() / 1000000) << " 秒(" << duration.count() <<" 微秒)" << std::endl;\
|
std::cout << text << ": " << std::fixed << std::setprecision(6) <<((double)duration.count() / 1000000) << " 秒(" << duration.count() <<" 微秒)" << std::endl;\
|
||||||
}while(false)
|
}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>(mutex_test());
|
||||||
|
|
||||||
|
auto ptr = std::make_shared<mutex_test>();
|
||||||
|
{
|
||||||
|
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(排序, 堆排序测试) {
|
TEST(排序, 堆排序测试) {
|
||||||
std::random_device rd;
|
std::random_device rd;
|
||||||
|
|||||||
10
src/mutex/shared_mutex.cpp
Normal file
10
src/mutex/shared_mutex.cpp
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
// 版权所有 (c) ling 保留所有权利。
|
||||||
|
// 除非另行说明,否则仅允许在DataStruct中使用此文件中的代码。
|
||||||
|
//
|
||||||
|
// 由 ling 创建于 24-7-10.
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "mutex/shared_mutex.h"
|
||||||
|
|
||||||
|
namespace ling {
|
||||||
|
} // ling
|
||||||
Reference in New Issue
Block a user