KBengine线程池实现分析

目录

Q:CBE是多线程的吗?可否部署在多台物理机上?

一、线程池线程生成

二、线程回调函数

三、线程池的具体使用


Q:CBE是多线程的吗?可否部署在多台物理机上?

A:CBE采用的是单线程(当然db读写等特殊任务依然会另开临时线程处理)多进程结构,不同的进程可以部署在不同的物理机上。理论上通过扩展机器数量和配置就可以扩展负载规模。

一、线程池线程生成

线程池实现在thread工程的threadpool类内.

由ThreadPool ->实例化 Thread实现

生成指定数量的线程

bool ThreadPool::createThreadPool(uint32 inewThreadCount, 
	uint32 inormalMaxThreadCount, uint32 imaxThreadCount)
{
	assert(!isInitialize_);
	INFO_MSG("ThreadPool::createThreadPool: creating  threadpool...\n");
	
	extraNewAddThreadCount_ = inewThreadCount;
	normalThreadCount_ = inormalMaxThreadCount;
	maxThreadCount_ = imaxThreadCount;
	
	for(uint32 i=0; i<normalThreadCount_; ++i)
	{
		TPThread* tptd = createThread(0);
		
		if(!tptd)
		{
			ERROR_MSG("ThreadPool::createThreadPool: error! \n");
			return false;
		}

		currentFreeThreadCount_++;	
		currentThreadCount_++;
		
		freeThreadList_.push_back(tptd);
		allThreadList_.push_back(tptd);
	}
	
	INFO_MSG(fmt::format("ThreadPool::createThreadPool: successfully({0}), "
		"newThreadCount={1}, normalMaxThreadCount={2}, maxThreadCount={3}\n",
			currentThreadCount_, extraNewAddThreadCount_, normalThreadCount_, maxThreadCount_));

	isInitialize_ = true;
	KBEngine::sleep(100);
	return true;
}

生成TPThread类对象

TPThread* ThreadPool::createThread(int threadWaitSecond, bool threadStartsImmediately)
{
	TPThread* tptd = new TPThread();

	if (threadStartsImmediately)
		tptd->createThread();

	return tptd;
}

调用API生成线程,Windows使用_beginthreadex, Linux使用pthread_create

THREAD_ID TPThread::createThread(void)
{
#if KBE_PLATFORM == PLATFORM_WIN32
	tidp_ = (THREAD_ID)_beginthreadex(NULL, 0, 
		&TPThread::threadFunc, (void*)this, NULL, 0);
#else	
	if(pthread_create(&tidp_, NULL, TPThread::threadFunc, 
		(void*)this)!= 0)
	{
		ERROR_MSG("createThread error!");
	}
#endif
	return tidp_;
}

二、线程回调函数

线程回调函数实现,通过参数arg把类指针传递进来

可以看到处理任务都是 tptd->processTask(task);这里

#if KBE_PLATFORM == PLATFORM_WIN32
unsigned __stdcall TPThread::threadFunc(void *arg)
#else	
void* TPThread::threadFunc(void* arg)
#endif
{
	TPThread * tptd = static_cast<TPThread*>(arg);
	ThreadPool* pThreadPool = tptd->threadPool();

	bool isRun = true;
	tptd->reset_done_tasks();

#if KBE_PLATFORM == PLATFORM_WIN32
#else			
	pthread_detach(pthread_self());
#endif

	tptd->onStart();

	while(isRun)
	{
		if(tptd->task() != NULL)
		{
			isRun = true;
		}
		else
		{
			tptd->reset_done_tasks();
			isRun = tptd->onWaitCondSignal();
		}

		if(!isRun || pThreadPool->isDestroyed())
		{
			if(!pThreadPool->hasThread(tptd))
				tptd = NULL;

			goto __THREAD_END__;
		}

		TPTask * task = tptd->task();
		if(task == NULL)
			continue;

		tptd->state_ = THREAD_STATE_BUSY;

		while(task && !tptd->threadPool()->isDestroyed())
		{
			tptd->inc_done_tasks();
			tptd->onProcessTaskStart(task);
			tptd->processTask(task);
			tptd->onProcessTaskEnd(task);
			
			// 尝试继续从任务队列里取出一个繁忙的未处理的任务
			TPTask * task1 = tptd->tryGetTask();

			if(!task1)
			{
				tptd->state_ = THREAD_STATE_PENDING;
				tptd->onTaskCompleted();
				break;
			}
			else
			{
				pThreadPool->addFiniTask(task);
				task = task1;
				tptd->task(task1);
			}
		}
	}

__THREAD_END__:
	if(tptd)
	{
		TPTask * task = tptd->task();
		if(task)
		{
			WARNING_MSG(fmt::format("TPThread::threadFunc: task {0:p} not finish, thread.{1:p} will exit.\n", 
				(void*)task, (void*)tptd));

			delete task;
		}

		tptd->onEnd();
		tptd->state_ = THREAD_STATE_END;
		tptd->reset_done_tasks();
	}

通过TPTask,对象传入

virtual void processTask(TPTask* pTask){ pTask->process(); }

通过查看TPTask的知道主要使用线程池的是dbmagr,也就是负责数据库查询的进程,多线程主要是满足进行数据库查询。

线程的堆栈调用顺序

三、线程池的具体使用

        查看另一篇《KBEngine,数据库查询消息流程》https://blog.csdn.net/hu123he/article/details/119790150

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值