Files
LayaNative2.0/Conch/source/common/misc/JCLayaThreadPool.h
T
2020-11-11 16:17:13 +08:00

301 lines
7.2 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
@file JCLayaThreadPool.h
@brief
@author hugao
@version 1.0
@date 2016_5_12
*/
#ifndef __JCLayaThreadPool_H__
#define __JCLayaThreadPool_H__
#include <thread>
#include <vector>
#include <list>
#include <functional>
#include "JCWorkSemaphore.h"
//#include "conchDebugThread.h"
#include "../util/JCCommonMethod.h"
#include <mutex>
#ifdef WIN32
extern void SetNameInternal(unsigned int thread_id, const char* name);
#elif ANDROID
#include <sys/syscall.h>
#include <unistd.h>
#define gettidv1() syscall(__NR_gettid)
#define gettidv2() syscall(SYS_gettid)
#elif __APPLE__
#include <pthread.h>
#endif
namespace laya
{
#ifdef __APPLE__
extern pthread_key_t s_tls_curDataThread;
#else
extern thread_local long* s_tls_curDataThread;
#endif
void ___datathread_onthreadstart(const char* threadname);
void ___datathread_onthreadstop(const char* threadname);
template<class _Tp>
/**
* @brief 管理多个工作线程。所有线程的工作任务类似。
* 这个是用来代替原来的threadpool的。因为原来的已经看不懂了,不好维护。
* TODO 临时写的,功能设计有些混乱。以后再整理
*/
class JCDataThread{
public:
typedef _Tp _DataType;
typedef std::function<void(void)> ThreadFunc;
typedef std::list<_DataType> __DataQueue;
typedef typename __DataQueue::iterator __DataQueueIter;
public:
JCDataThread(){
m_pThread = NULL;
m_nThreadNo=0;
}
~JCDataThread(){
Stop();
}
bool Start( ThreadFunc p_pfnThreadFunc ){
if(m_pThread){
Stop();
}
m_ThreadFunc = p_pfnThreadFunc;
//TODO m_Semaphore 的stop标记现在不是原子的。
//std::interprocess::ipcdetail::atomic_write32( &m_bWantToStop, 0 );
m_pThread = new std::thread(std::bind(&JCDataThread::__ThreadEntry,this));
if( 0 == m_pThread )
return false;
return true;
}
int getNum() {
int num = 0;
{
m_Mutex.lock();
num = m_Datas.size();
m_Mutex.unlock();
}
return num;
}
void SendData( _DataType p_Data ){
int num =0;
{
std::unique_lock<std::recursive_mutex> _lock(m_Mutex);
m_Datas.push_back(p_Data);
num=m_Datas.size();
}
m_Semaphore.setDataNum(num);
}
bool WaitData( _DataType *p_pData ){
m_Semaphore.waitUntilHasData();
{
std::unique_lock<std::recursive_mutex> _lock(m_Mutex);
if(m_Datas.size()>0){
*p_pData = m_Datas.front();
m_Datas.pop_front();
m_Semaphore.setDataNum(m_Datas.size());
return true;
}
}
return false;
}
void Stop(){
if(!m_pThread)
return;
m_Semaphore.notifyAllWait();
m_pThread->join();
m_Semaphore.reset();
delete m_pThread;
m_pThread = NULL;
}
/**
* 多次尝试join
* 返回true表示成功join了
* timeout 每次尝试的超时时间,单位是毫秒
* traStopWorker 返回true表示希望停止尝试。参数是当前尝试次数和用户定义参数
*/
typedef bool (*tryStopWorker)(int,void*);
bool tryStop(int timeout, tryStopWorker func, void* userdata) {
return false;
}
void ClearTask(){
std::unique_lock<std::recursive_mutex> _lock(m_Mutex);
m_Datas.clear();
}
//必须在启动线程前设置。
void setName(const char* p_pszName){
m_strName = p_pszName;
}
protected:
void __ThreadEntry(){
#ifdef __APPLE__
pthread_setspecific(s_tls_curDataThread,(void*)this);
#else
s_tls_curDataThread = (long*)this;
#endif
___datathread_onthreadstart(m_strName.c_str());
m_ThreadFunc();
___datathread_onthreadstop(m_strName.c_str());
}
//std::uint32_t m_bWantToStop;
JCWorkSemaphore m_Semaphore;
std::recursive_mutex m_Mutex;
__DataQueue m_Datas;
ThreadFunc m_ThreadFunc;
std::thread* m_pThread;
std::string m_strName;
public:
int m_nThreadNo;
};
template<class _Tp>
class JCThreadPool{
public:
typedef _Tp _DataType;
typedef JCDataThread<_Tp> dtthread;
JCThreadPool(){
m_nThreadNum = 0;
m_AllThread = 0;
}
~JCThreadPool(){
stop();
}
void init(int p_nThread,std::function<void(void)> p_fun){
stop();
{
std::unique_lock<std::recursive_mutex> _lock(m_Mutex);
m_nThreadNum=p_nThread;
m_AllThread = new dtthread* [m_nThreadNum];
for( int i=0; i<m_nThreadNum; i++){
m_AllThread[i] = new dtthread();
m_AllThread[i]->m_nThreadNo=i;
m_AllThread[i]->setName(m_strThreadName.c_str());
m_AllThread[i]->Start(p_fun);
}
}
}
//发送到任务最少的线程中
bool sendToThread(_DataType p_dt) {
if (m_nThreadNum <= 0)
return false;
m_Mutex.lock();
if (m_nThreadNum == 1) {
m_AllThread[0]->SendData(p_dt);
}
else {
int minv = -1;
int mini = -1;
for (int i = 0; i < m_nThreadNum; i++) {
int n = m_AllThread[i]->getNum();
if (minv<0 || n < minv) {
minv = n;
mini = i;
}
}
if (mini >= 0) {
m_AllThread[mini]->SendData(p_dt);
}
else {
m_Mutex.unlock();
return false;
}
}
m_Mutex.unlock();
return true;
}
bool sendToThread(_DataType p_dt, int p_nThread){
std::unique_lock<std::recursive_mutex> _lock(m_Mutex);
if(p_nThread>=m_nThreadNum){
return false;
}
m_AllThread[p_nThread]->SendData(p_dt);
return true;
}
void stop(){
std::unique_lock<std::recursive_mutex> _lock(m_Mutex);
for( int i=0; i<m_nThreadNum; i++){
m_AllThread[i]->Stop();
delete m_AllThread[i];
}
delete [] m_AllThread;
m_AllThread = NULL;
m_nThreadNum = 0;
}
bool waitData(_DataType* pData ){
#ifdef __APPLE__
dtthread* pThread=(dtthread*)pthread_getspecific(s_tls_curDataThread);
return pThread->WaitData(pData);
#else
dtthread* pThread = (dtthread*)s_tls_curDataThread;
return pThread->WaitData(pData);
#endif
}
void* getCurThread(){
#ifdef __APPLE__
dtthread* pThread=(dtthread*)pthread_getspecific(s_tls_curDataThread);
return pThread;
#else
dtthread* pThread = (dtthread*)s_tls_curDataThread;
return pThread;
#endif
}
int getCurThreadNo(void* p_pThread){
dtthread* pThread=(dtthread*)p_pThread;
return pThread->m_nThreadNo;
}
bool waitData(void* p_pThread, _DataType* pData){
dtthread* pThread=(dtthread*)p_pThread;
return pThread->WaitData(pData);
}
int getThreadNum(){ return m_nThreadNum;}
void ClearDataOfThread(int i){
if(i>=m_nThreadNum)
return;
{
std::unique_lock<std::recursive_mutex> _lock(m_Mutex);
m_AllThread[i]->ClearTask();
}
}
void setThreadName(const char* p_pszName){
m_strThreadName = p_pszName;
}
protected:
std::recursive_mutex m_Mutex;
dtthread** m_AllThread;
int m_nThreadNum;
std::string m_strThreadName;
};
};
//------------------------------------------------------------------------------
#endif //__JCLayaThreadPool_H__
//-----------------------------END FILE--------------------------------