功能介绍
此类实现了如下功能:
在程序启动时即创建若干个线程(即线程池),当有任务需要执行时,将需要执行的任务放入任务队列,唤醒一个空闲线程进行任务的处理,处理完任务后线程继续进入睡眠 状态。
类
类名 | 内容 |
---|---|
CAutoLock | 自动锁 |
CMutex | 该类实现了互斥锁的封装 |
CTask | 任务封装,ITask的实例 |
CTaskThread | 任务线程类 |
CThread | 线程类封装,实现了睡眠线程唤醒机制 |
ITask | 接口类,定义了几个虚函数 |
ITaskThreadSink | 任务线程槽接口,主要为了在启动任务前或任务结束后需要执行一些相关操作而实现 |
自动锁
/** @class CAutoLock
* @brief 自动锁
*
* 该类实现了对CMutex类对象的自动上锁与解锁,它只提供了两个方法,构造与析构
* 在构造函数里对CMutex类对象上锁,在析构函数里进行解锁
*/
class CAutoLock
{
public:
/** @brief 构造函数,自动上锁 */
CAutoLock(CMutex *pMutex)
{
m_pMutex = pMutex;
m_pMutex->Lock();
}
/** @brief 析构函数,自动解锁 */
virtual ~CAutoLock()
{
m_pMutex->Unlock();
}
private:
CMutex * m_pMutex;
};
#endif
互斥锁的封装
/** @class CMutex
* @brief 该类实现了互斥锁的封装
*/
class CMutex
{
public:
/** @brief 构造函数 */
CMutex();
/** @brief 析构函数 */
virtual ~CMutex();
/** @brief 上锁操作
* @return 0-成功,非0-失败
*/
int Lock();
/** @brief 解锁操作
* @return 0-成功,非0-失败
*/
int Unlock();
/** @brief 尝试上锁操作,非阻塞
* @return 0-成功,非0-失败
*/
int TryLock();
/** @brief 获取互斥锁
* @return 返回互斥锁指针
*/
pthread_mutex_t * GetPthreadMutex() { return &m_mutex; }
protected:
private:
pthread_mutex_t m_mutex;
};
任务的封装
#define PRIORITY_LOW 1
#define PRIORITY_HIGH 4
/** @class CTask
* @brief 任务封装,ITask的实例
*/
class CTask : public ITask
{
public:
CTask(int p = PRIORITY_LOW);
virtual ~CTask();
/** @brief 预执行任务 */
virtual void PreExec();
/** @brief 需要执行的任务 */
virtual void Execute() = 0 ;
/** @brief 执行后处理 */
virtual void PostExec();
/** @brief 获取当前任务优先级
* @return 当前任务的优先级别
*/
virtual int Priority(void);
/** @brief 设备任务优先级
* @param p - 任务优先级,从1到4为从低到高
*/
virtual void Priority(int p);
private:
int m_priority;
};
接口类
其中继承的ITask
为:
/** @class ITask 任务封装接口
* @brief 接口类,定义了几个虚函数
*/
class ITask
{
public:
/** @brief 析构函数 */
virtual ~ITask() { }
/** @brief 预执行任务 */
virtual void PreExec() { }
/** @brief 执行主任务 */
virtual void Execute() = 0;
/** @brief 执行后收尾工作 */
virtual void PostExec() { }
/** @brief 设置优先级 */
virtual void Priority(int p) = 0;
/** @brief 获取优先级 */
virtual int Priority() = 0;
};
线程类封装
/** @class CTaskThread
* @brief 任务线程类
*
* 该类的使用方法为:先创建一个ITask对象,并实现其需要执行的函数代码,
* 需要实现的函数主要为:PreExec(), Execute(),PostExec(),
* 接着通过调用SetTask()方法将ITask对象作为参数传入,使其作为线程需要执行的任务
* 在SetTask()函数中会调用线程的SignalThread()函数唤醒线程以执行任务。
* 在启动任务前,若设置了ITaskThreadSink对象,则会先执行其OnTaskStart()函数,
* 在结束任务后,若设置了ITaskThreadSink对象,则会执行其OnTaskStop()函数
*/
class CTaskThread : public CThread
{
public:
/** @brief 构造函数
* @param pSink - 线程任务启动前或结束后需执行相关操作时,可传入此参数
*/
CTaskThread(ITaskThreadSink *pSink = NULL);
/** @brief 析构函数 */
virtual ~CTaskThread();
/** @brief 启动线程执行pTask中的任务,传入不同的ITask对象可以让线程执行不同的任务\n
* 执行完任务后,线程继续进入等待状态
* @param pTask - 需要执行的任务对象,会执行其PreExec(),Execute()和PostExec()函数
* @return 0 - 操作成功, 否则失败
* @note 返回0时并不代表任务执行一定正确,并且在执行完任务会,会删除pTask对象
*/
int SetTask(ITask *pTask);
/** @brief 获取当前CTaskThread对象的地址
* @return 本对象地址
*/
unsigned long GetTaskThreadId() const ;
protected:
virtual void ExecuteTask();
private:
ITaskThreadSink *m_pSink;
ITask *m_pTask;
CMutex m_cMutexTask;
unsigned long m_nId;
};
其中继承CThread
为:
/** @class CThread
* @brief 线程类封装,实现了睡眠线程唤醒机制
*/
class CThread
{
public:
/** @brief 构造函数, 条件变量在此时初始化 */
CThread();
/** @brief 析构函数 */
virtual ~CThread();
protected:
/** @brief 线程函数
*
* 在TheThread()线程函数中调用此函数,为执行任务循环的主体
* 为保证线程只有一个实例在运行,在此函数开始执行前会先上锁保护。
* 直到此函数结束才释放锁,故在调用Start函数时需注意
*/
virtual void Thread();
/** @brief 执行任务函数,在线程被唤醒时执行的函数 */
virtual void ExecuteTask();
public:
/** @brief 启动线程任务循环 */
virtual int Start();
/** @brief 结束此线程,会等待线程退出 */
virtual int Kill();
/** @brief 检查线程是否在运行
* @return true - 在运行,false - 未运行
*/
bool IsRunning() { return m_bRunning; }
protected:
/** @brief 创建线程时的线程函数 */
static void * TheThread(void *param);
/** @brief 设置线程的运行状态
* @param b true - 已运行, false - 未运行
*/
void SetRunning(bool b);
/** @brief 设置线程的结束标记
* @param b - true 结束线程
*/
void SetEndFlag(bool b);
/** @brief 获取线程结束标记
* @return true - 线程已结束 false - 线程未结束
*/
bool IsEndFlagSet() { return m_bEndFlag; }
/** @brief 发送信号唤醒线程开始执行任务 */
void SignalThread();
private:
pthread_t m_hThread;
bool m_bRunning;
bool m_bEndFlag;
pthread_cond_t m_Cond;
CMutex m_cMutexStatus;
CMutex m_cMutexThread;
};
线程槽
/** @class ITaskThreadSink
* @brief 任务线程槽接口,主要为了在启动任务前或任务结束后需要执行一些相关操作而实现
*/
class ITaskThreadSink
{
public:
/** @brief 析构函数 */
virtual ~ITaskThreadSink() { }
/** @brief 在启动任务前需执行的操作 */
virtual int OnTaskStart(CTaskThread *thread) = 0;
/** @brief 在任务执行完成后需执行的操作 */
virtual int OnTaskStop(CTaskThread *thread) = 0;
};