#ifndef __HI_MW_THREAD_H__
#define __HI_MW_THREAD_H__
#include <pthread.h>
#include <unistd.h>
#include "hi_type.h"
class HiMWThread;
class IHiMWThreadEvt
{
public:
virtual void onHiMWThreadExit(HiMWThread* pHiMWThread) = 0;
virtual ~IHiMWThreadEvt(){}
};
class HiMWThread
{
public:
typedef void (*HiMWThreadFunc)(const void* arg);
typedef struct {
volatile bool wait;
volatile bool once;
volatile bool exit;
} HiMWThreadStat;
typedef enum {
ONCE = 0x1 << 0,
REPEAT = 0x1 << 1,
WAIT = 0x1 << 2,
} HiMWThreadFlag;
public:
HiMWThread(HiMWThreadFunc func = NULL, const void* arg = NULL, IHiMWThreadEvt* pEvt = NULL);
virtual ~HiMWThread();
void run(unsigned int flag = ONCE);
void suspend();
void resume();
void exit();
void exitAndJoin();
protected:
virtual void run(const void* arg){HI_UNUSED(arg);};
private:
static void* loop(void* arg);
void task();
private:
HiMWThreadFunc mThreadFunc;
const void* mArg;
IHiMWThreadEvt* mEvt;
pthread_t mId;
HiMWThreadStat mStat;
pthread_mutex_t mLock;
pthread_cond_t mCond;
};
#endif
#define LOG_NDEBUG 0
#define LOG_TAG "HiMW@Hi_mw_thread.cpp"
#include "hi_mw_thread.h"
#include "hi_mw_log.h"
#include "hi_mw_common.h"
HiMWThread::HiMWThread(HiMWThreadFunc func, const void* arg, IHiMWThreadEvt* pEvt)
: mThreadFunc(func), mArg(arg), mEvt(pEvt), mId(0)
{
mStat.wait = false;
mStat.once = false;
mStat.exit = true;
HI_S32 s32Ret = HI_SUCCESS;
s32Ret = pthread_mutex_init(&mLock, NULL);
RET_CHECK_ERR_LOG(s32Ret, "pthread_cond_init fail, ret:0x%x", s32Ret);
s32Ret = pthread_cond_init(&mCond, NULL);
RET_CHECK_ERR_LOG(s32Ret, "pthread_cond_init fail, ret:0x%x", s32Ret);
}
HiMWThread::~HiMWThread()
{
HI_S32 s32Ret = HI_SUCCESS;
s32Ret = pthread_mutex_lock(&mLock);
RET_CHECK_ERR_LOG(s32Ret, "pthread_cond_init fail, ret:0x%x", s32Ret);
if (!mStat.exit)
{
s32Ret = pthread_mutex_unlock(&mLock);
RET_CHECK_ERR_LOG(s32Ret, "pthread_cond_init fail, ret:0x%x", s32Ret);
s32Ret = pthread_join(mId, NULL);
RET_CHECK_ERR_LOG(s32Ret, "pthread_cond_init fail, ret:0x%x", s32Ret);
}
else
{
s32Ret = pthread_mutex_unlock(&mLock);
RET_CHECK_ERR_LOG(s32Ret, "pthread_cond_init fail, ret:0x%x", s32Ret);
}
s32Ret = pthread_mutex_destroy(&mLock);
RET_CHECK_ERR_LOG(s32Ret, "pthread_cond_init fail, ret:0x%x", s32Ret);
s32Ret = pthread_cond_destroy(&mCond);
RET_CHECK_ERR_LOG(s32Ret, "pthread_cond_init fail, ret:0x%x", s32Ret);
}
void HiMWThread::exit()
{
HI_S32 s32Ret = HI_SUCCESS;
s32Ret = pthread_mutex_lock(&mLock);
RET_CHECK_ERR_LOG(s32Ret, "pthread_mutex_lock fail, ret:0x%x", s32Ret);
if (!mStat.exit)
{
mStat.exit = true;
mStat.wait = false;
s32Ret = pthread_cond_signal(&mCond);
RET_CHECK_ERR_LOG(s32Ret, "pthread_cond_signal fail, ret:0x%x", s32Ret);
}
s32Ret = pthread_mutex_unlock(&mLock);
RET_CHECK_ERR_LOG(s32Ret, "pthread_mutex_unlock fail, ret:0x%x", s32Ret);
}
void HiMWThread::exitAndJoin()
{
HI_S32 s32Ret = HI_SUCCESS;
s32Ret = pthread_mutex_lock(&mLock);
RET_CHECK_ERR_LOG(s32Ret, "pthread_mutex_lock fail, ret:0x%x", s32Ret);
if (!mStat.exit)
{
mStat.exit = true;
mStat.wait = false;
s32Ret = pthread_cond_signal(&mCond);
RET_CHECK_ERR_LOG(s32Ret, "pthread_cond_signal fail, ret:0x%x", s32Ret);
s32Ret = pthread_mutex_unlock(&mLock);
RET_CHECK_ERR_LOG(s32Ret, "pthread_mutex_unlock fail, ret:0x%x", s32Ret);
s32Ret = pthread_join(mId, NULL);
RET_CHECK_ERR_LOG(s32Ret, "pthread_join fail, ret:0x%x", s32Ret);
return;
}
s32Ret = pthread_mutex_unlock(&mLock);
RET_CHECK_ERR_LOG(s32Ret, "pthread_mutex_unlock fail, ret:0x%x", s32Ret);
LOGW("Thread not run");
}
void HiMWThread::run(unsigned int flag)
{
HI_S32 s32Ret = HI_SUCCESS;
s32Ret = pthread_mutex_lock(&mLock);
RET_CHECK_ERR_LOG(s32Ret, "pthread_mutex_lock fail, ret:0x%x", s32Ret);
if (!mStat.exit)
{
mStat.exit = true;
mStat.wait = false;
s32Ret = pthread_cond_signal(&mCond);
RET_CHECK_ERR_LOG(s32Ret, "pthread_cond_signal fail, ret:0x%x", s32Ret);
s32Ret = pthread_mutex_unlock(&mLock);
RET_CHECK_ERR_LOG(s32Ret, "pthread_mutex_unlock fail, ret:0x%x", s32Ret);
s32Ret = pthread_join(mId, NULL);
RET_CHECK_ERR_LOG(s32Ret, "pthread_join fail, ret:0x%x", s32Ret);
s32Ret = pthread_mutex_lock(&mLock);
RET_CHECK_ERR_LOG(s32Ret, "pthread_mutex_lock fail, ret:0x%x", s32Ret);
}
mStat.exit = false;
mStat.wait = true;
mStat.once = flag & ONCE;
if (~flag & WAIT)
{
mStat.wait = false;
}
s32Ret = pthread_mutex_unlock(&mLock);
RET_CHECK_ERR_LOG(s32Ret, "pthread_mutex_unlock fail, ret:0x%x", s32Ret);
s32Ret = pthread_create(&mId, NULL, loop, this);
RET_CHECK_ERR_LOG(s32Ret, "pthread_create fail, ret:0x%x", s32Ret);
}
void HiMWThread::suspend()
{
HI_S32 s32Ret = HI_SUCCESS;
s32Ret = pthread_mutex_lock(&mLock);
RET_CHECK_ERR_LOG(s32Ret, "pthread_mutex_lock fail, ret:0x%x", s32Ret);
if (!mStat.exit)
{
if (mStat.wait)
{
s32Ret = pthread_mutex_unlock(&mLock);
RET_CHECK_ERR_LOG(s32Ret, "pthread_mutex_unlock fail, ret:0x%x", s32Ret);
return;
}
mStat.wait = true;
}
s32Ret = pthread_mutex_unlock(&mLock);
RET_CHECK_ERR_LOG(s32Ret, "pthread_mutex_unlock fail, ret:0x%x", s32Ret);
}
void HiMWThread::resume()
{
HI_S32 s32Ret = HI_SUCCESS;
s32Ret = pthread_mutex_lock(&mLock);
RET_CHECK_ERR_LOG(s32Ret, "pthread_mutex_lock fail, ret:0x%x", s32Ret);
if (!mStat.exit)
{
if (!mStat.wait)
{
s32Ret = pthread_mutex_unlock(&mLock);
RET_CHECK_ERR_LOG(s32Ret, "pthread_mutex_unlock fail, ret:0x%x", s32Ret);
return;
}
mStat.wait = false;
s32Ret = pthread_cond_signal(&mCond);
RET_CHECK_ERR_LOG(s32Ret, "pthread_cond_signal fail, ret:0x%x", s32Ret);
}
s32Ret = pthread_mutex_unlock(&mLock);
RET_CHECK_ERR_LOG(s32Ret, "pthread_mutex_unlock fail, ret:0x%x", s32Ret);
}
void* HiMWThread::loop(void* arg)
{
HiMWThread* ptr = reinterpret_cast<HiMWThread*>(arg);
while (!ptr->mStat.exit)
{
ptr->task();
}
if (ptr->mEvt)
{
ptr->mEvt->onHiMWThreadExit(ptr);
}
return NULL;
}
void HiMWThread::task()
{
HI_S32 s32Ret = HI_SUCCESS;
s32Ret = pthread_mutex_lock(&mLock);
RET_CHECK_ERR_LOG(s32Ret, "pthread_mutex_lock fail, ret:0x%x", s32Ret);
while (mStat.wait)
{
s32Ret = pthread_cond_wait(&mCond, &mLock);
RET_CHECK_ERR_LOG(s32Ret, "pthread_cond_wait fail, ret:0x%x", s32Ret);
}
if (mStat.exit)
{
s32Ret = pthread_mutex_unlock(&mLock);
RET_CHECK_ERR_LOG(s32Ret, "pthread_mutex_unlock fail, ret:0x%x", s32Ret);
return;
}
mStat.wait = mStat.once;
s32Ret = pthread_mutex_unlock(&mLock);
RET_CHECK_ERR_LOG(s32Ret, "pthread_mutex_unlock fail, ret:0x%x", s32Ret);
if (!mThreadFunc)
{
return run(mArg);
}
return mThreadFunc(mArg);
}