2019-08-19 19:19:58 +08:00
|
|
|
|
#ifndef HGL_THREAD_INCLUDE
|
|
|
|
|
#define HGL_THREAD_INCLUDE
|
|
|
|
|
|
|
|
|
|
#include<hgl/type/DataType.h>
|
2022-02-08 11:10:20 +08:00
|
|
|
|
#include<hgl/type/SortedSets.h>
|
2020-09-03 15:52:46 +08:00
|
|
|
|
#include<hgl/type/String.h>
|
2019-08-19 19:19:58 +08:00
|
|
|
|
#include<hgl/thread/ThreadMutex.h>
|
2019-08-27 20:26:44 +08:00
|
|
|
|
#include<hgl/log/LogInfo.h>
|
2019-08-19 19:19:58 +08:00
|
|
|
|
|
|
|
|
|
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
|
2020-07-07 19:14:42 +08:00
|
|
|
|
u8char thread_addr[(sizeof(thread_ptr)<<1)+1];
|
2019-08-19 19:19:58 +08:00
|
|
|
|
|
|
|
|
|
DataToUpperHexStr(thread_addr,(uint8 *)&tp,sizeof(thread_ptr));
|
|
|
|
|
|
|
|
|
|
thread_addr_string=thread_addr;
|
|
|
|
|
#endif//_DEBUG
|
|
|
|
|
|
|
|
|
|
return(true);
|
|
|
|
|
}
|
|
|
|
|
|
2022-07-07 21:32:35 +08:00
|
|
|
|
virtual void ProcEndThread(){} ///<结程结束运行函数,在Execute后被调用
|
2019-08-19 19:19:58 +08:00
|
|
|
|
|
2022-07-07 21:32:35 +08:00
|
|
|
|
virtual bool DeletedAfterExit()const{return true;} ///<返回在退出线程时,是否删除本对象(注:此函数不可动态变动值)
|
2019-08-19 19:19:58 +08:00
|
|
|
|
|
|
|
|
|
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); ///<等待多个线程中的一个完成
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 简单的多线程管理
|
|
|
|
|
*/
|
|
|
|
|
template<typename THREAD> class MultiThreadManage
|
|
|
|
|
{
|
|
|
|
|
protected:
|
|
|
|
|
|
2022-02-08 11:10:20 +08:00
|
|
|
|
SortedSets<THREAD *> thread_set;
|
2019-08-19 19:19:58 +08:00
|
|
|
|
|
|
|
|
|
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;
|
|
|
|
|
}
|
|
|
|
|
|
2023-08-14 20:01:44 +08:00
|
|
|
|
thread_set.Clear();
|
2019-08-19 19:19:58 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 启动所有线程
|
|
|
|
|
* @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
|