栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

c++ 11读写锁

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

c++ 11读写锁

参考:C++中的RAII_一蓑烟雨任平生 也无风雨也无晴-CSDN博客

C++11实现模板化(通用化)RAII机制_10km的专栏-CSDN博客_c++11 raii

无锁编程:c++11基于atomic实现共享读写锁(写优先)_10km的专栏-CSDN博客

raii.h

#include 
#include 
namespace gyd {
	
	template
	struct no_const {
		using type = typename std::conditional::value, typename std::remove_const::type, T>::type;
	};
	
	class raii {
	public:
		using fun_type = std::function;
		
		explicit raii(fun_type release, fun_type acquire = [] {}, bool default_com = true) noexcept :
			_commit(default_com), _release(release) {
			acquire();
		}
		
		~raii() noexcept {
			if (_commit)
				_release();
		}
		
		raii(raii&& rv)noexcept :_commit(rv._commit), _release(rv._release) {
			rv._commit = false;
		};
		
		raii(const raii&) = delete;
		
		raii& operator=(const raii&) = delete;

		
		raii& commit(bool c = true)noexcept { _commit = c; return *this; };
	private:
		
		bool _commit;
	protected:
		
		std::function _release;
	}; 

	
	template
	class raii_var {
	public:
		using    _Self = raii_var;
		using	acq_type = std::function;
		using	rel_type = std::function;
		explicit raii_var(acq_type acquire, rel_type release) noexcept :
			_resource(acquire()), _release(release) {
			//构造函数中执行申请资源的动作acquire()并初始化resource;
		}
		
		raii_var(raii_var&& rv) :
			_resource(std::move(rv._resource)),
			_release(std::move(rv._release))
		{
			rv._commit = false;//控制右值对象析构时不再执行_release
		}
		
		~raii_var() noexcept {
			if (_commit)
				_release(_resource);
		}
		
		_Self& commit(bool c = true)noexcept { _commit = c; return *this; };
		
			T& get() noexcept { return _resource; }
		T& operator*() noexcept
		{
			return get();
		}

		
		template
		typename std::enable_if::value, _T>::type operator->() const noexcept
		{
			return _resource;
		}
		template
		typename std::enable_if::value, _T*>::type operator->() const noexcept
		{
			return std::addressof(_resource);
		}

	private:
		
		bool	_commit = true;
		T	_resource;
		rel_type _release;
	};
	
	template
	raii make_raii(RES & res, M_REL rel, M_ACQ acq, bool default_com = true)noexcept {
		// 编译时检查参数类型
		// 静态断言中用到的is_class,is_member_function_pointer等是用于编译期的计算、查询、判断、转换的type_traits类,
		// 有点类似于java的反射(reflect)提供的功能,不过只能用于编译期,不能用于运行时。
		// 关于type_traits的详细内容参见:http://www.cplusplus.com/reference/type_traits/
		static_assert(std::is_class::value, "RES is not a class or struct type.");
		static_assert(std::is_member_function_pointer::value, "M_REL is not a member function.");
		static_assert(std::is_member_function_pointer::value, "M_ACQ is not a member function.");
		assert(nullptr != rel && nullptr != acq);
		auto p_res = std::addressof(const_cast::type&>(res));
		return raii(std::bind(rel, p_res), std::bind(acq, p_res), default_com);
	}
	
	template
	raii make_raii(RES & res, M_REL rel, bool default_com = true)noexcept {
		static_assert(std::is_class::value, "RES is not a class or struct type.");
		static_assert(std::is_member_function_pointer::value, "M_REL is not a member function.");
		assert(nullptr != rel);
		auto p_res = std::addressof(const_cast::type&>(res));
		return raii(std::bind(rel, p_res), [] {}, default_com);
	}
} 

RWLock.h

#include 
#include 
#include 
#include 
#include 
#include "raii.h"
using namespace gyd;

class RWLock {
#define WRITE_LOCK_STATUS -1
#define FREE_STATUS 0
private:
	
	static const  std::thread::id NULL_THEAD;
	const bool WRITE_FIRST;
	
	std::thread::id m_write_thread_id;
	
	std::atomic_int m_lockCount;
	
	std::atomic_uint m_writeWaitCount;
public:
	// 禁止复制构造函数
	RWLock(const RWLock&) = delete;
	// 禁止对象赋值操作符
	RWLock& operator=(const RWLock&) = delete;
	//RWLock& operator=(const RWLock&) volatile = delete;
	RWLock(bool writeFirst = false);;//默认为读优先模式
	virtual ~RWLock() = default;
	int readLock();
	int readUnlock();
	int writeLock();
	int writeUnlock();

	//other class defineition code....
	static auto make_read_guard(RWLock &lock)->decltype(make_raii(lock, &RWLock::readUnlock, &RWLock::readLock, true)) {
		return make_raii(lock, &RWLock::readUnlock, &RWLock::readLock, true);
	}

	//other class defineition code....
	static auto make_write_guard(RWLock &lock)->decltype(make_raii(lock, &RWLock::writeUnlock, &RWLock::writeLock, true)) {
		return make_raii(lock, &RWLock::writeUnlock, &RWLock::writeLock, true);
	}
	// 将读取锁的申请和释放动作封装为raii对象,自动完成加锁和解锁管理
	raii read_guard()const noexcept {
		return make_raii(*this, &RWLock::readUnlock, &RWLock::readLock);
	}
	// 将写入锁的申请和释放动作封装为raii对象,自动完成加锁和解锁管理
	raii write_guard()noexcept {
		return make_raii(*this, &RWLock::writeUnlock, &RWLock::writeLock);
	}
};

RWLock.cpp

#include "RWLock.h"

RWLock::RWLock(bool writeFirst) :
	WRITE_FIRST(writeFirst),
	m_write_thread_id(),
	m_lockCount(0),
	m_writeWaitCount(0) {
}
int RWLock::readLock() {
	// ==时为独占写状态,不需要加锁
	if (std::this_thread::get_id() != this->m_write_thread_id) {
		int count;
		if (WRITE_FIRST)//写优先模式下,要检测等待写的线程数为0(m_writeWaitCount==0)
			do {
				while ((count = m_lockCount) == WRITE_LOCK_STATUS || m_writeWaitCount > 0);//写锁定时等待
			} while (!m_lockCount.compare_exchange_weak(count, count + 1));
		else
			do {
				while ((count = m_lockCount) == WRITE_LOCK_STATUS); //写锁定时等待
			} while (!m_lockCount.compare_exchange_weak(count, count + 1));
	}
	return m_lockCount;
}
int RWLock::readUnlock() {
	// ==时为独占写状态,不需要加锁
	if (std::this_thread::get_id() != this->m_write_thread_id)
		--m_lockCount;
	return m_lockCount;
}
int RWLock::writeLock() {
	// ==时为独占写状态,避免重复加锁
	if (std::this_thread::get_id() != this->m_write_thread_id) {
		++m_writeWaitCount;//写等待计数器加1
		// 没有线程读取时(加锁计数器为0),置为-1加写入锁,否则等待
		for (int zero = FREE_STATUS; !this->m_lockCount.compare_exchange_weak(zero, WRITE_LOCK_STATUS); zero = FREE_STATUS);
		--m_writeWaitCount;//获取锁后,计数器减1
		m_write_thread_id = std::this_thread::get_id();
	}
	return m_lockCount;
}
int RWLock::writeUnlock() {
	if (std::this_thread::get_id() != this->m_write_thread_id) {
		throw std::runtime_error("writeLock/Unlock mismatch");
	}
	assert(WRITE_LOCK_STATUS == m_lockCount);
	m_write_thread_id = NULL_THEAD;
	m_lockCount.store(FREE_STATUS);
	return m_lockCount;
}
const std::thread::id RWLock::NULL_THEAD;

调用方式

RWLock lock;
void make_raii_test(){
	auto guard=RWLock::make_read_guard(lock);
	//do something...
}
int main(){
	make_raii_test();
}
RWLock lock;
void make_raii_test(){
	auto guard=RWLock::make_write_guard(lock);
	//do something...
}
int main(){
	make_raii_test();
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/529092.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号