216 lines
5.4 KiB
C++
216 lines
5.4 KiB
C++
/**
|
|
@file JCWorkerThread.cpp
|
|
@brief
|
|
@author James
|
|
@version 1.0
|
|
@date 2016_5_12
|
|
*/
|
|
|
|
#include "JCWorkerThread.h"
|
|
//#include "../misc/conchDebugThread.h"
|
|
#include "../util/JCCommonMethod.h"
|
|
#include "../util/Log.h"
|
|
#ifdef WIN32
|
|
#include <windows.h>
|
|
#include <process.h>
|
|
//2013.3.5
|
|
//cswuyg
|
|
//参考 chromium源码: src\base\threading\platform_thread_win.cc
|
|
|
|
// The information on how to set the thread name comes from
|
|
// a MSDN article: http://msdn2.microsoft.com/en-us/library/xcb2z8hs.aspx
|
|
const DWORD kVCThreadNameException = 0x406D1388;
|
|
|
|
typedef struct tagTHREADNAME_INFO {
|
|
DWORD dwType; // Must be 0x1000.
|
|
LPCSTR szName; // Pointer to name (in user addr space).
|
|
DWORD dwThreadID; // Thread ID (-1=caller thread).
|
|
DWORD dwFlags; // Reserved for future use, must be zero.
|
|
} THREADNAME_INFO;
|
|
|
|
// This function has try handling, so it is separated out of its caller.
|
|
void SetNameInternal(unsigned int thread_id, const char* name)
|
|
{
|
|
//只在调试的时候生效
|
|
if (!::IsDebuggerPresent())
|
|
return;
|
|
THREADNAME_INFO info;
|
|
info.dwType = 0x1000;
|
|
info.szName = name;
|
|
info.dwThreadID = thread_id;
|
|
info.dwFlags = 0;
|
|
|
|
__try
|
|
{
|
|
RaiseException(kVCThreadNameException, 0, sizeof(info)/sizeof(DWORD), reinterpret_cast<DWORD_PTR*>(&info));
|
|
}
|
|
__except(EXCEPTION_CONTINUE_EXECUTION)
|
|
{
|
|
}
|
|
}
|
|
#elif ANDROID
|
|
#include <sys/syscall.h>
|
|
#define gettidv1() syscall(__NR_gettid)
|
|
#define gettidv2() syscall(SYS_gettid)
|
|
#elif OHOS
|
|
#include <sys/syscall.h>
|
|
#include "unistd.h"
|
|
#define gettidv1() syscall(__NR_gettid)
|
|
#define gettidv2() syscall(SYS_gettid)
|
|
#endif
|
|
|
|
namespace laya{
|
|
#ifdef __APPLE__
|
|
pthread_key_t JCWorkerThread::s_tls_curThread;
|
|
#else
|
|
thread_local long* JCWorkerThread::s_tls_curThread = nullptr; //这个虽然是静态的。但每个线程之间不会干扰
|
|
#endif
|
|
|
|
JCWorkerThread* JCWorkerThread::getCurThread(){
|
|
#ifdef __APPLE__
|
|
return (JCWorkerThread*)pthread_getspecific(s_tls_curThread);
|
|
#else
|
|
return (JCWorkerThread*)s_tls_curThread;
|
|
#endif
|
|
}
|
|
|
|
JCWorkerThread::JCWorkerThread(bool p_bStart){
|
|
m_bStop = false;
|
|
m_bStopOnDestroy = true;
|
|
m_AllListener.resize(JCWorkerThread::Event_Num);
|
|
m_bdbgThreadStarted=false;
|
|
m_pUserData=0;
|
|
if(p_bStart)
|
|
start();
|
|
}
|
|
|
|
JCWorkerThread::~JCWorkerThread(){
|
|
if(m_bStopOnDestroy)
|
|
stop();
|
|
}
|
|
|
|
void JCWorkerThread::setLoopFunc( std::function<void(void)> loopFunc ){
|
|
if(m_bdbgThreadStarted){
|
|
printf("After the start of the thread,you can't set loopFunc again,Mainly afraid to call the first 'post',than call 'setLoopFunc' Cause tasks to spread between m_ThreadTasks and m_FuncQueue\n");
|
|
throw -1;
|
|
}
|
|
m_funcLoop = loopFunc;
|
|
}
|
|
|
|
void JCWorkerThread::start(){
|
|
m_bStop = false;
|
|
//m_pThread = new std::thread( workFunc );
|
|
m_ThreadTasks.Start(std::bind(&JCWorkerThread::_threadProc,this));
|
|
//m_ThreadTasks.CreateThread( std::bind(&workerThread::_threadProc,this));
|
|
m_bdbgThreadStarted=true;
|
|
}
|
|
|
|
void JCWorkerThread::stop(){
|
|
if(m_bStop)
|
|
return;
|
|
m_bStop = true;
|
|
m_ThreadTasks.Stop();
|
|
m_bdbgThreadStarted=false;
|
|
}
|
|
|
|
bool JCWorkerThread::tryStop(int timeout, JCDataThread<runObj>::tryStopWorker func, void* userdata) {
|
|
if (m_bStop)
|
|
return true;
|
|
m_bStop = true;
|
|
bool bret = m_ThreadTasks.tryStop(timeout, func, userdata);
|
|
m_bdbgThreadStarted = false;
|
|
return bret;
|
|
}
|
|
void JCWorkerThread::post(runObj func){
|
|
if (m_bStop)
|
|
return;
|
|
if( !m_funcLoop){
|
|
m_ThreadTasks.SendData(func);
|
|
}else{
|
|
m_QueueLock.lock();
|
|
m_FuncQueue.push_back(func);
|
|
m_QueueLock.unlock();
|
|
}
|
|
}
|
|
|
|
void JCWorkerThread::runQueue(){
|
|
std::vector<runObj> workQueue;
|
|
m_QueueLock.lock();
|
|
std::swap(workQueue, m_FuncQueue);
|
|
m_QueueLock.unlock();
|
|
for( int i=0; i<(int)workQueue.size(); i++){
|
|
workQueue[i]();
|
|
}
|
|
}
|
|
|
|
|
|
void JCWorkerThread::_runLoop(){
|
|
_defRunLoop();
|
|
}
|
|
|
|
void JCWorkerThread::_defRunLoop(){
|
|
//设置名字
|
|
#ifdef WIN32
|
|
{
|
|
DWORD thid = GetCurrentThreadId();
|
|
SetNameInternal(thid, m_strName.c_str());
|
|
LOGI("start thread:%s,%d", m_strName.c_str(), thid);
|
|
//threadInfoLog("start thread:%s,%d", m_strName.c_str(), thid);
|
|
}
|
|
#elif ANDROID || OHOS
|
|
{
|
|
LOGI("start thread:%s,%d", m_strName.c_str(), (int)gettidv1());
|
|
//threadInfoLog("start thread:%s,%ld", m_strName.c_str(), gettidv1());
|
|
}
|
|
#endif
|
|
//开始事件
|
|
JCEventEmitter::evtPtr startEvt(new JCEventBase);
|
|
startEvt->m_nID=JCWorkerThread::Event_threadStart;
|
|
emit(startEvt);
|
|
|
|
runObj task;
|
|
while(!m_bStop){
|
|
if( !m_funcLoop ){
|
|
//现在的waitdata返回false不再表示要退出。
|
|
//事件唤醒流程
|
|
//if( !m_ThreadTasks.WaitData(&task) )
|
|
// break;
|
|
if( m_ThreadTasks.WaitData(&task))
|
|
task();
|
|
}else{
|
|
//固定循环流程
|
|
runQueue();
|
|
m_funcLoop();
|
|
}
|
|
}
|
|
|
|
//退出事件
|
|
JCEventEmitter::evtPtr stopEvt(new JCEventBase);
|
|
stopEvt->m_nID=JCWorkerThread::Event_threadStop;
|
|
emit(stopEvt);
|
|
}
|
|
|
|
void JCWorkerThread::_threadProc(){
|
|
//设置tls
|
|
#ifdef __APPLE__
|
|
pthread_setspecific(s_tls_curThread,(void*)this);
|
|
#else
|
|
s_tls_curThread = (long*)this;
|
|
#endif
|
|
//去掉try了,因为可能导致流程混乱,卡死
|
|
_runLoop();
|
|
}
|
|
|
|
void JCWorkerThread::setThreadName(const char* p_pszName){
|
|
m_strName = p_pszName;
|
|
}
|
|
bool JCWorkerThread::isStop()
|
|
{
|
|
return m_bStop;
|
|
}
|
|
}
|
|
//------------------------------------------------------------------------------
|
|
|
|
|
|
//-----------------------------END FILE--------------------------------
|