first commit
This commit is contained in:
240
inc/hgl/thread/SwapData.h
Normal file
240
inc/hgl/thread/SwapData.h
Normal file
@@ -0,0 +1,240 @@
|
||||
#ifndef HGL_THREAD_SWAP_DATA_INCLUDE
|
||||
#define HGL_THREAD_SWAP_DATA_INCLUDE
|
||||
|
||||
#include<hgl/thread/ThreadMutex.h>
|
||||
#include<hgl/thread/Semaphore.h>
|
||||
|
||||
namespace hgl
|
||||
{
|
||||
/**
|
||||
* 单向多线程数据交换模板<br>
|
||||
* 适用环境为多个线程向其投递数据,一个线程接收数据。接收方在每次处理前交换数据指针,以达到最小线程切换代价
|
||||
*/
|
||||
template<typename T> class SwapData
|
||||
{
|
||||
protected:
|
||||
|
||||
T data[2];
|
||||
|
||||
int post_index;
|
||||
int recv_index;
|
||||
|
||||
ThreadMutex lock;
|
||||
|
||||
protected:
|
||||
|
||||
void _Swap()
|
||||
{
|
||||
if(recv_index){recv_index=0;post_index=1;}
|
||||
else{recv_index=1;post_index=0;}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
SwapData()
|
||||
{
|
||||
recv_index=0;
|
||||
post_index=1;
|
||||
}
|
||||
|
||||
virtual ~SwapData()=default;
|
||||
|
||||
/**
|
||||
* 获取投递方数据访问权
|
||||
*/
|
||||
T &GetPost()
|
||||
{
|
||||
lock.Lock();
|
||||
|
||||
return data[post_index];
|
||||
}
|
||||
|
||||
/**
|
||||
* 释放多线程投递方数据访问权
|
||||
*/
|
||||
void ReleasePost()
|
||||
{
|
||||
lock.Unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* 取得接收方数据访问权
|
||||
*/
|
||||
T &GetReceive(){return data[recv_index];}
|
||||
|
||||
/**
|
||||
* 交换双方数据
|
||||
*/
|
||||
void Swap()
|
||||
{
|
||||
lock.Lock();
|
||||
|
||||
this->_Swap();
|
||||
|
||||
lock.Unlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* 尝试交换双方数据
|
||||
*/
|
||||
bool TrySwap()
|
||||
{
|
||||
if(!lock.TryLock())
|
||||
return(false);
|
||||
|
||||
this->_Swap();
|
||||
|
||||
lock.Unlock();
|
||||
return(true);
|
||||
}
|
||||
|
||||
#ifndef __APPLE__
|
||||
/**
|
||||
* 尝试交换双方数据
|
||||
*/
|
||||
bool WaitSwap(const double time_out)
|
||||
{
|
||||
if(!lock.WaitLock(time_out))
|
||||
return(false);
|
||||
|
||||
this->_Swap();
|
||||
|
||||
lock.Unlock();
|
||||
return(true);
|
||||
}
|
||||
#endif//__APPLE__
|
||||
};//template<typename T> class SwapData
|
||||
|
||||
/**
|
||||
* 信号自动交换数据访问模板
|
||||
*/
|
||||
template<typename T> class SemSwapData:public SwapData<T>
|
||||
{
|
||||
Semaphore sem;
|
||||
|
||||
public:
|
||||
|
||||
using SwapData<T>::SwapData;
|
||||
~SemSwapData()=default;
|
||||
|
||||
/**
|
||||
* 释放接收信号
|
||||
* @param count 信号个数
|
||||
*/
|
||||
void PostSem(int count=1)
|
||||
{
|
||||
sem.Post(count);
|
||||
}
|
||||
|
||||
/**
|
||||
* 等待获取一个信号并交换前后台数据
|
||||
* @param time_out 等待时长
|
||||
*/
|
||||
bool WaitSemSwap(const double time_out=5)
|
||||
{
|
||||
if(!sem.Acquire(time_out))
|
||||
return(false);
|
||||
|
||||
this->Swap();
|
||||
return(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 尝试获取一个信号并交换前后台数据
|
||||
*/
|
||||
bool TrySemSwap()
|
||||
{
|
||||
if(!sem.TryAcquire())
|
||||
return(false);
|
||||
|
||||
this->Swap();
|
||||
return(true);
|
||||
}
|
||||
};//template<typename T> class SemSwapData:public SwapData<T>
|
||||
|
||||
/**
|
||||
* SwapData模板自动释放Post工具模板
|
||||
*/
|
||||
template<typename T> class PostToSwapData
|
||||
{
|
||||
SwapData<T> *swap_data;
|
||||
T *post;
|
||||
|
||||
public:
|
||||
|
||||
PostToSwapData(SwapData<T> *sd)
|
||||
{
|
||||
swap_data=sd;
|
||||
|
||||
if(swap_data)
|
||||
post=&(swap_data->GetPost());
|
||||
else
|
||||
post=nullptr;
|
||||
}
|
||||
|
||||
~PostToSwapData()
|
||||
{
|
||||
if(swap_data)
|
||||
swap_data->ReleasePost();
|
||||
}
|
||||
|
||||
T *operator ->(){return post;}
|
||||
};//template<typename T> class PostToSwapData
|
||||
|
||||
/**
|
||||
* SemSwapData模板自动释放Post工具模板
|
||||
*/
|
||||
template<typename T> class PostToSemSwapData
|
||||
{
|
||||
SemSwapData<T> *swap_data;
|
||||
T *post;
|
||||
|
||||
public:
|
||||
|
||||
PostToSemSwapData(SemSwapData<T> *sd)
|
||||
{
|
||||
swap_data=sd;
|
||||
|
||||
if(swap_data)
|
||||
post=&(swap_data->GetPost());
|
||||
else
|
||||
post=nullptr;
|
||||
}
|
||||
|
||||
~PostToSemSwapData()
|
||||
{
|
||||
if(swap_data)
|
||||
{
|
||||
swap_data->ReleasePost();
|
||||
swap_data->PostSem();
|
||||
}
|
||||
}
|
||||
|
||||
T *operator ->(){return post;}
|
||||
};//template<typename T> class PostToSemSwapData
|
||||
|
||||
/**
|
||||
* 使用范例
|
||||
*
|
||||
* using EventQueue=Queue<int>;
|
||||
* using MTEventQueue=SemSwapData<EventQueue>;
|
||||
* using MTEventPost=PostToSemSwapData<EventQueue>;
|
||||
*
|
||||
* MTEventQueue mt_event_queue;
|
||||
*
|
||||
* 新方式:
|
||||
* MTEventPost post(mt_event_queue);
|
||||
*
|
||||
* post.Push(1);
|
||||
*
|
||||
* 直接模式:
|
||||
* EventQueue &eq=mt_event_queue.GetPost();
|
||||
*
|
||||
* eq->Push(1);
|
||||
*
|
||||
* mt_event_queue.ReleasePost();
|
||||
* mt_event_queue.PostSem();
|
||||
*
|
||||
*/
|
||||
}//namespace hgl
|
||||
#endif//HGL_THREAD_SWAP_DATA_INCLUDE
|
Reference in New Issue
Block a user