容器 线程安全包装
实现对容器使用线程锁的包装模板类,省去重复 写各种简单的容器线程包装
一些前置工具来自于 https://gitee.com/keybox/actor-library/blob/master/actor/commons/commons_utils.h
互斥锁包装模板
template <typename T,typename Lock = std::mutex>
class LContainer{
// struct Lock{ //要求 Lock 类必须实现的方法
// void lock(){}
// bool try_lock(){}
// void unlock(){}
// };
public:
LContainer():__lock(new Lock()){}
LContainer(const T& data):__lock(new Lock()),__data(data){}
LContainer(T&& data):__lock(new Lock()),__data(std::move(data)){}
public: //重置内部数据
auto operator=(const T& data){
reset(data);
return lock();
}
auto operator=(T&& data){
reset(data);
return lock();
}
auto operator->(){return lock();} //写
auto operator->() const {return lock();} //读
auto operator*() {return lock();} //写
auto operator*() const {return lock();} //读
// operator const bool() const {auto l = lock();return this->__data;}
public:
//尝试上锁
auto try_lock(){return defer_unlock(__lock->try_lock());}
auto try_lock() const {return defer_unlock(__lock->try_lock());}
//上锁
auto lock(){
__lock->lock();
return defer_unlock();
}
auto lock() const {
__lock->lock();
return defer_unlock();
}
public:
//尝试交换内部数据
bool try_swit(T& data){
if (!__lock->try_lock())return false;
auto l = defer_unlock();
std::swap(std::ref(data),__data);
return true;
}
//尝试重置内部数据为其他
bool try_reset(const T& data){
if (!__lock->try_lock())return false;
auto l = defer_unlock();
__data = data;
return true;
}
bool try_reset(T&& data){
if (!__lock->try_lock())return false;
auto l = defer_unlock();
__data = data;
return true;
}
void reset(const T& data){
auto l = lock();
__data = data;
}
void reset(T& data){
auto l = lock();
std::swap(data,__data);
}
protected:
//解锁器 //写锁 (上锁有效性) //当上锁无效时将返回false的锁代理
auto defer_unlock(bool vaild = true)
{return make_defer_ref([this](){__lock->unlock();},__data,vaild);}
//常量方法 解锁器 //读锁 //当内容数据不是指针时
template<typename T1 = T,Type_Is::is_no_pointer<T1>* = nullptr>
auto defer_unlock(bool vaild = true) const
{return make_defer_ref([this](){__lock->unlock();},__data,vaild);}
//内部数据是指针
template<typename T1 = T,Type_Is::is_pointer<T1>* = nullptr>
auto defer_unlock(bool vaild = true) const{
const auto& data = *this->__data;
auto* rul_ptr = &data;
return make_defer_ua([this](){__lock->unlock();},rul_ptr,vaild);
}
protected:
T __data; //要保护的数据 //可以是容器或变量
PtrAgent<Lock> __lock; //线程锁
// friend struct iterator<LContainer>; //还没实现完
};
读写锁包装模板
//通过继承LContainer 互斥锁模板,重新实现 const 函数完成
template <typename T,typename Lock = std::shared_mutex>
class RWContainer : public LContainer<T,Lock>{
// struct Lock{ //锁类必须存在这些方法
// void lock(){}
// void lock_shared(){}
// bool try_lock(){}
// bool try_lock_shared(){}
// void unlock(){}
// void unlock_shared(){}
// };
public:
using LContainer<T,Lock>::LContainer;
//修改是上写锁的,但返回的值是上读锁的
auto operator=(const T& data){
this->reset(data);
return lock_shared();
}
auto operator=(T&& data){
this->reset(data);
return lock_shared();
}
auto operator->() const {return lock_shared();}
auto operator*() const {return lock_shared();}
auto operator->() {return LContainer<T,Lock>::operator->();}
auto operator*() {return LContainer<T,Lock>::operator*();}
// operator const bool() const {auto l = lock_shared();return this->__data;}
public:
//尝试上读锁
auto try_lock_shared() const {
return defer_unlock_shared(this->__lock->try_lock_shared());
}
//上读锁
auto lock_shared() const {
this->__lock->lock_shared();
return defer_unlock_shared();
}
protected:
//读锁器 //内容数据是指针
template<typename T1 = T,Type_Is::is_pointer<T1>* = nullptr>
auto defer_unlock_shared(bool vaild = true) const{
const auto& data = *this->__data;
auto* rul_ptr = &data;
return make_defer([this](){this->__lock->unlock_shared();},rul_ptr,vaild);
}
//读锁器 //内容数据不是指针
template<typename T1 = T,Type_Is::is_no_pointer<T1>* = nullptr>
auto defer_unlock_shared(bool vaild = true) const
{return make_defer_ref([this](){this->__lock->unlock_shared();},this->__data,vaild);}
protected:
// friend struct iterator<RWContainer>; //还没有完成
};
读写锁测试
ReThreadPool是一个很简单的线程池,来自 https://gitee.com/keybox/actor-library/blob/master/actor/thread_pool.h
void rwcontent_test(uint64_t count = 1000,uint64_t tcount = 15,uint64_t rcount = 1){
auto con = RWContainer<uint64_t>();
uint64_t a = 0;
for (uint64_t i = 0;i < count; i++){
a += 1 * tcount;
}
auto pool = ReThreadPool(tcount,[&](){
for (uint64_t i = 0;i < count; i++){
(*con).data() += 1;
}
});
auto p_pool = ReThreadPool(rcount,[&](){
for (uint64_t i = 0;i<10;i++){
const auto& c = con;
std::cout<<(*c).data()<<std::endl;
}
});
pool.join();
p_pool.join();
std::cout<<a<<" "<<(*con).data()<<std::endl;
}
源码地址
https://gitee.com/keybox/actor-library/blob/master/actor/commons/concurrent_commons.h