Linux学习之"线程的再封装"
先上代码,主要是线程类"CLThread":
头文件:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#ifndef CLTHREAD_H
#define CLTHREAD_H
#include <pthread.h>
#include "CLExecutive.h"
#include "CLStatus.h"
#include "CLEvent.h"
/*
CLThread代表了一个线程,该类对象的生存期,即线程的生存期
该类对象必须从堆中分配,且不必调用delete释放内存
构造函数中的bWaitForDeath用于指示是否需要等待新线程结束。默认
情况是不需要的。若需要则设置为true,并且需保证最后一定要调用
WaitForDeath函数,否则资源无法释放
Run、WaitForDeath函数如果返回成功,则只能调用一次。
*/
class CLThread : public CLExecutive
{
public:
/*
构造和析构函数出错时,会抛出字符串类型异常
*pExecutiveFunctionProvider参数必须是从堆中分配的
*/
explicit CLThread(CLExecutiveFunctionProvider *pExecutiveFunctionProvider);
CLThread(CLExecutiveFunctionProvider *pExecutiveFunctionProvider, bool bWaitForDeath);
virtual ~CLThread();
virtual CLStatus Run(void *pContext = 0);
virtual CLStatus WaitForDeath();
private:
static void* StartFunctionOfThread(void *pContext);
private:
void *m_pContext;
CLEvent m_EventForWaitingForNewThread;
CLEvent m_EventForWaitingForOldThread;
pthread_t m_ThreadID;
bool m_bWaitForDeath;
bool m_Flag;
};
#endif
增加一些成员变量及一个构造函数,稍后解释。
实现:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include "CLThread.h"
#include "CLExecutiveFunctionProvider.h"
#include "CLEvent.h"
#include "CLLog.h"
CLThread::CLThread(CLExecutiveFunctionProvider *pExecutiveFunctionProvider) : CLExecutive(pExecutiveFunctionProvider)
{
m_pContext = 0;
m_bWaitForDeath = false;
m_Flag = false;
}
CLThread::CLThread(CLExecutiveFunctionProvider *pExecutiveFunctionProvider, bool bWaitForDeath) : CLExecutive(pExecutiveFunctionProvider)
{
m_pContext = 0;
m_bWaitForDeath = bWaitForDeath;
m_Flag = false;
}
CLThread::~CLThread()
{
}
CLStatus CLThread::Run(void *pContext)
{
if(m_Flag)
return CLStatus(-1, 0);
m_pContext = pContext;
int r = pthread_create(&m_ThreadID, 0, StartFunctionOfThread, this);
if(r != 0)
{
CLLog::WriteLogMsg("In CLThread::Run(), pthread_create error", r);
delete this;
return CLStatus(-1, 0);
}
m_Flag = true;
if(!m_bWaitForDeath)
{
r = pthread_detach(m_ThreadID);
if(r != 0)
CLLog::WriteLogMsg("In CLThread::Run(), pthread_detach error", r);
}
CLStatus s = m_EventForWaitingForNewThread.Wait();
if(!s.IsSuccess())
{
CLLog::WriteLogMsg("In CLThread::Run(), m_EventForWaitingForNewThread.Wait error", 0);
}
CLStatus s1 = m_EventForWaitingForOldThread.Set();
if(!s1.IsSuccess())
{
CLLog::WriteLogMsg("In CLThread::Run(), m_EventForWaitingForOldThread.Set error", 0);
}
return CLStatus(0, 0);
}
void* CLThread::StartFunctionOfThread(void *pThis)
{
CLThread *pThreadThis = (CLThread *)pThis;
void *pContext = pThreadThis->m_pContext;
pThreadThis->m_pContext = NULL;
CLStatus s = pThreadThis->m_EventForWaitingForNewThread.Set();
if(!s.IsSuccess())
{
CLLog::WriteLogMsg("In CLThread::StartFunctionOfThread(), m_pEventForThreadSynchronization.Set error", 0);
}
CLStatus s1 = pThreadThis->m_EventForWaitingForOldThread.Wait();
if(!s1.IsSuccess())
{
CLLog::WriteLogMsg("In CLThread::StartFunctionOfThread(), m_EventForWaitingForOldThread.Wait error", 0);
}
pThreadThis->m_pExecutiveFunctionProvider->RunExecutiveFunction(pContext);
if(!(pThreadThis->m_bWaitForDeath))
delete pThreadThis;
return 0;
}
CLStatus CLThread::WaitForDeath()
{
if(!m_bWaitForDeath)
return CLStatus(-1, 0);
if(!m_Flag)
return CLStatus(-1, 0);
int r = pthread_join(m_ThreadID, 0);
if(r != 0)
{
CLLog::WriteLogMsg("In CLThread::WaitForDeath(), pthread_join error", r);
return CLStatus(-1, 0);
}
delete this;
return CLStatus(0, 0);
}
m_bWaitForDeath:让用户指定他是否需要等待新线程死亡,并添加了与之相关的构造函数。
m_Flag:防止用户在一个CLThread对象上多次调用Run(),防止在没有Run()的情况下就WaitForDeath()
m_EventForWaitingForNewThread和m_EventForWaitingForOldThread:用于同步主线程和子线程,保证:1.“在Run方法退出之前,新线程不会死亡”,2.“Run方法返回前,应保证新线程确实已经被创建”。用于避免由于在新线程先退出再WaitForDeath()而引发异常。
在Run()中,当新线程创建后,把m_Flag置为true;
若用户不选择等待线程结束(不会调用WaitForDeath()),则调用pthread_detach()使线程新线程进入detached状态,以便该线程运行结束后会自动释放所有资源。关于为什么要使其进入detached状态(包括其他状态),参见"百度百科pthread_detach"。
然后,调用CLEvent类型的m_EventForWaitingForNewThread的Wait()来等待新线程创建完成;在退出前,m_EventForWaitingForOldThread.Set()告诉新线程可以继续运行,执行具体的业务逻辑。退出后,即可调用WaitForDeath()等待新线程结束。
一单子线程运行到StartFunctionOfThread(),就意味着新线程的创建已经完成,此时,m_EventForWaitingForNewThread.Set()告诉主线程的Run()函数可以继续,自己则在m_EventForWaitingForOldThread上等待Run()发出的退出信号。
执行完具体业务逻辑后,子线程返回到StartFunctionOfThread()中,在退出前,如果用户选择子线程自行结束,则这是子线程最后释放资源的机会:delete pThreadThis释放自己所占有的资源。
在WaitForDeath()中,若用户没有选择m_bWaitForDeath或新线程尚未创建,直接退出;退出前,同StartFunctionOfThread()一样,释放自身资源。