8 Star 29 Fork 21

10km / common_source_cpp

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
RWLock.hpp 3.71 KB
一键复制 编辑 原始数据 按行查看 历史
/*
* ShareLock.h
*
* Created on: 2021年10月9日
* Author: guyadong
*/
#ifndef COMMON_SOURCE_CPP_RWLOCK_HPP_
#define COMMON_SOURCE_CPP_RWLOCK_HPP_
#include <cstdlib>
#include <cassert>
#include <atomic>
#include <thread>
#include "raii.h"
namespace gdface {
inline namespace mt{
/*
* atomic实现读写资源锁,独占写,共享读,禁止复制构造函数和'='赋值操作符
* WRITE_FIRST为true时为写优先模式,如果有线程等待读取(m_write_wait_count>0)则等待,优先让写线程先获取锁
* 允许嵌套加锁
* readLock/Unlock 实现共享的读取加/解锁,线程数不限
* writeLock/Unlock 实现独占的写入加/解锁,同时只允许一个线程写入,当有线程在读取时,写入线程阻塞,当写入线程执行时,所有的读取线程都被阻塞。
*/
class RWLock {
#define WRITE_LOCK_STATUS -1
#define FREE_STATUS 0
private:
const bool WRITE_FIRST;
/* 用于判断当前是否是写线程 */
std::thread::id m_write_thread_id;
/* 资源锁计数器,-1为写状态,0为自由状态,>0为共享读取状态 */
std::atomic_int m_lock_count;
/* 等待写线程计数器 */
std::atomic_uint m_write_wait_count;
public:
// 禁止复制构造函数
RWLock(const RWLock&) = delete;
// 禁止赋值操作符
RWLock& operator=(const RWLock&) = delete;
/* 允许移动构造 */
RWLock(RWLock&& rv):
WRITE_FIRST(rv.WRITE_FIRST),
m_write_thread_id(rv.m_write_thread_id),
m_lock_count(rv.m_lock_count.load()),
m_write_wait_count(rv.m_write_wait_count.load()){
// 初始状态的对象才可以移动
assert(m_write_thread_id==std::thread::id()&&0==m_lock_count&&0==m_write_wait_count);
};
explicit RWLock(bool writeFirst = false)noexcept:
WRITE_FIRST(writeFirst),
m_write_thread_id(),
m_lock_count(0),
m_write_wait_count(0) {};//默认为读优先模式
virtual ~RWLock()=default;
int readLock() noexcept
{
// ==时为独占写状态,不需要加锁
if (std::this_thread::get_id() != this->m_write_thread_id) {
int count;
if (WRITE_FIRST)//写优先模式下,要检测等待写的线程数为0(m_write_wait_count==0)
do {
while (m_write_wait_count > 0 || (count = m_lock_count) < 0); //写锁定时等待
} while (!m_lock_count.compare_exchange_weak(count, count + 1));
else
do {
while ((count = m_lock_count) < 0); //写锁定时等待
} while (!m_lock_count.compare_exchange_weak(count, count + 1));
}
return m_lock_count;
}
int readUnlock() noexcept
{
// ==时为独占写状态,不需要加锁
if (std::this_thread::get_id() != this->m_write_thread_id)
--m_lock_count;
return m_lock_count;
}
int writeLock() noexcept
{
if (std::this_thread::get_id() != this->m_write_thread_id) {
++m_write_wait_count;//写等待计数器加1
// 没有线程读取时(加锁计数器为0),置为-1加写入锁,否则等待
for (int zero = FREE_STATUS; !this->m_lock_count.compare_exchange_weak(zero, WRITE_LOCK_STATUS); zero = FREE_STATUS);
--m_write_wait_count;//获取锁后,计数器减1
m_write_thread_id = std::this_thread::get_id();
}
else
--m_lock_count;// ==时为独占写状态
return m_lock_count;
}
int writeUnlock() noexcept
{
assert(std::this_thread::get_id() == this->m_write_thread_id&&WRITE_LOCK_STATUS >= m_lock_count);
if (WRITE_LOCK_STATUS == m_lock_count) {
m_write_thread_id = std::thread::id();
m_lock_count.store(FREE_STATUS);
}
else
++m_lock_count;
return m_lock_count;
}
raii read_guard()const noexcept{
return gdface::make_raii(*this,&RWLock::readUnlock,&RWLock::readLock);
}
raii write_guard()noexcept{
return gdface::make_raii(*this,&RWLock::writeUnlock,&RWLock::writeLock);
}
};
}/* namespace mt */
} /* namespace gdface */
#endif /* COMMON_SOURCE_CPP_RWLOCK_HPP_ */
C++
1
https://gitee.com/l0km/common_source_cpp.git
git@gitee.com:l0km/common_source_cpp.git
l0km
common_source_cpp
common_source_cpp
master

搜索帮助