231 lines
6.2 KiB
C++
231 lines
6.2 KiB
C++
#ifndef HGL_THREAD_INCLUDE
|
||
#define HGL_THREAD_INCLUDE
|
||
|
||
#include<hgl/type/DataType.h>
|
||
#include<hgl/type/Set.h>
|
||
#include<hgl/type/BaseString.h>
|
||
#include<hgl/thread/ThreadMutex.h>
|
||
#include<hgl/log/LogInfo.h>
|
||
|
||
namespace hgl
|
||
{
|
||
void WaitThreadExit(thread_ptr tp,const double &time_out);
|
||
|
||
/**
|
||
* 线程类.本类用于建立一个线程并管理它。<br>
|
||
* Sleep和Exit函数是给线程内的程序使用的;而Start,Close,Pause,Rewind是给线程外的程序使用的。<br>
|
||
* 使用本类只需要重载本类,并将代码写在Execute函数内即可。<br>
|
||
* 执行大概为:<br>
|
||
* if(ProcStartThread()) <br>
|
||
* while(Execute()); <br>
|
||
* else <br>
|
||
* return(0);
|
||
* <br>
|
||
* ProcEndThread();
|
||
*/
|
||
class Thread ///线程类
|
||
{
|
||
friend void WaitThread(Thread **,int,double);
|
||
|
||
private:
|
||
|
||
thread_ptr tp=0;
|
||
|
||
ThreadMutex live_lock;
|
||
ThreadMutex exit_lock;
|
||
|
||
friend THREAD_FUNC ThreadFunc(Thread *tc);
|
||
|
||
#ifdef _DEBUG
|
||
UTF8String thread_addr_string; ///<线程地址用字符串,调试使用
|
||
#endif//_DEBUG
|
||
|
||
public:
|
||
|
||
virtual ~Thread()=default;
|
||
|
||
#ifdef _DEBUG
|
||
const UTF8String &GetThreadAddressString()const{return thread_addr_string;} ///<取得线程地址字符串
|
||
#endif//_DEBUG
|
||
|
||
/**
|
||
* 线程执行函数,会被反复调用
|
||
* @return true 继续执行
|
||
* @return false 退出执行
|
||
*/
|
||
virtual bool Execute()=0; ///<线程的运行函数
|
||
|
||
virtual bool ProcStartThread() ///<线程启动运行函数,在Execute前被调用
|
||
{
|
||
#ifdef _DEBUG
|
||
u8char thread_addr[(sizeof(thread_ptr)<<1)+1];
|
||
|
||
DataToUpperHexStr(thread_addr,(uint8 *)&tp,sizeof(thread_ptr));
|
||
|
||
thread_addr_string=thread_addr;
|
||
#endif//_DEBUG
|
||
|
||
return(true);
|
||
}
|
||
|
||
virtual void ProcEndThread(){} ///<结程结束运行函数,在Execute后被调用
|
||
|
||
virtual bool IsExitDelete()const{return true;} ///<返回在退出线程时,是否删除本对象(注:此函数不可动态变动值)
|
||
|
||
bool IsLive() ///<当前线程是否还活着
|
||
{
|
||
if(live_lock.TryLock())
|
||
{
|
||
//成功了,证明这个线程已经关闭了
|
||
live_lock.Unlock();
|
||
return(false);
|
||
}
|
||
|
||
return(true);
|
||
}
|
||
|
||
public: //线程运行控制
|
||
|
||
virtual bool Start(); ///<开始运行当前线程
|
||
|
||
virtual bool IsCurThread(); ///<是否是当前线程
|
||
|
||
virtual void Exit() ///<退出当前线程(其它线程调用)
|
||
{
|
||
exit_lock.Unlock();
|
||
}
|
||
|
||
/**
|
||
* (线程外部调用)退出当前线程,并等待其完成退出<br>
|
||
* @param time_out 等待的时间,如果为0表示等到线程运行结束为止。默认为0
|
||
*/
|
||
virtual void WaitExit(const double &time_out=0)
|
||
{
|
||
if(!tp)
|
||
return;
|
||
|
||
thread_ptr self_tp=tp;
|
||
|
||
Exit();
|
||
|
||
WaitThreadExit(self_tp,time_out);
|
||
}
|
||
};//class Thread
|
||
|
||
void WaitThread(Thread **,int,double time=0); ///<等待多个线程中的一个完成
|
||
|
||
bool CreateThread(Thread *); ///<创建一个线程
|
||
|
||
/**
|
||
* 简单的多线程管理
|
||
*/
|
||
template<typename THREAD> class MultiThreadManage
|
||
{
|
||
protected:
|
||
|
||
Set<THREAD *> thread_set;
|
||
|
||
public:
|
||
|
||
virtual ~MultiThreadManage()
|
||
{
|
||
Close();
|
||
}
|
||
|
||
THREAD *GetThread(int index)
|
||
{
|
||
THREAD *result;
|
||
|
||
if(thread_set.Get(index,result))
|
||
return result;
|
||
|
||
return nullptr;
|
||
}
|
||
|
||
/**
|
||
* 增加一个线程到合集中
|
||
* @return 是否增加成功
|
||
*/
|
||
bool Add(THREAD *p)
|
||
{
|
||
if(!p)return(false);
|
||
|
||
return(thread_set.Add(p)!=-1);
|
||
}
|
||
|
||
/**
|
||
* 删除一个线程
|
||
*/
|
||
void Delete(THREAD *p)
|
||
{
|
||
if(!p)return;
|
||
|
||
thread_set.Delete(p);
|
||
}
|
||
|
||
/**
|
||
* 关闭所有线程
|
||
*/
|
||
void Close()
|
||
{
|
||
const int count=thread_set.GetCount();
|
||
|
||
THREAD **p=thread_set.GetData();
|
||
|
||
for(int i=0;i<count;i++)
|
||
{
|
||
(*p)->WaitExit();
|
||
++p;
|
||
}
|
||
|
||
thread_set.ClearData();
|
||
}
|
||
|
||
/**
|
||
* 启动所有线程
|
||
* @return 成功启动的线程数量
|
||
*/
|
||
int Start()
|
||
{
|
||
const int count=thread_set.GetCount();
|
||
|
||
THREAD **p=thread_set.GetData();
|
||
|
||
int total=0;
|
||
|
||
for(int i=0;i<count;i++)
|
||
{
|
||
if((*p)->Start())
|
||
++total;
|
||
|
||
++p;
|
||
}
|
||
|
||
return total;
|
||
}
|
||
|
||
/**
|
||
* 检查还有几个线程活着
|
||
*/
|
||
int IsLive()
|
||
{
|
||
const int count=thread_set.GetCount();
|
||
|
||
THREAD **p=thread_set.GetData();
|
||
|
||
int total=0;
|
||
|
||
for(int i=0;i<count;i++)
|
||
{
|
||
if((*p)->IsLive())
|
||
++total;
|
||
|
||
++p;
|
||
}
|
||
|
||
return total;
|
||
}
|
||
};//class MultiThreadManage
|
||
}//namespace hgl
|
||
#endif//HGL_THREAD_INCLUDE
|