#ifndef __CUVLOOP__H_
#define __CUVLOOP__H_
#include "UvThread.h"
#include "UvBase.h"
#include "UvMutex.h"
#include <queue>
class CUvLoop : public CUvThread, public CUvBase
{
public:
CUvLoop();
~CUvLoop();
public:
int PushUvBase(CUvBase* pUvBase);
public:
static void AsyncCb(uv_async_t* pHandle);
protected:
int OnInit();
int OnThreadRun();
private:
void PopUvBase();
private:
uv_loop_t mstUvLoop;
uv_async_t mstUvAsync;
int miBakFdNum;
std::queue<CUvBase*> mqueUvBase;
CUvMutex mcQueBaseMutex;
};
#endif
#include "UvLoop.h"
#define MAX_UV_LOOP_BAK_FD 10000
CUvLoop::CUvLoop(){
if (uv_loop_init(&mstUvLoop) == 0) {
SetUvLoop(&mstUvLoop);
}
miBakFdNum = 0;
}
CUvLoop::~CUvLoop(){
if (nullptr != mpUvLoop) {
uv_loop_close(mpUvLoop);
mpUvLoop = nullptr;
}
}
int CUvLoop::OnInit() {
uv_handle_set_data((uv_handle_t*)&mstUvAsync, (void*)this);
uv_async_init(mpUvLoop, &mstUvAsync, CUvLoop::AsyncCb);
return Start();
}
void CUvLoop::AsyncCb(uv_async_t* pHandle) {
CUvLoop* pUvLoop = (CUvLoop*)uv_handle_get_data((uv_handle_t*)pHandle);
if (nullptr != pUvLoop) {
pUvLoop->PopUvBase();
}
}
void CUvLoop::PopUvBase() {
CUvBase* pUvBase = nullptr;
mcQueBaseMutex.Lock();
if (!mqueUvBase.empty()) {
pUvBase = mqueUvBase.front();
mqueUvBase.pop();
}
mcQueBaseMutex.UnLock();
if (nullptr != pUvBase) {
pUvBase->SetUvLoop(mpUvLoop);
pUvBase->Init();
}else {
return;
}
miBakFdNum = uv_backend_fd(mpUvLoop);
LOG_INFO("miBakFdNum = %d", miBakFdNum);
PopUvBase();
}
int CUvLoop::PushUvBase(CUvBase* pUvBase) {
ASSERT_RET_VALUE(nullptr != mpUvLoop && nullptr != pUvBase && miBakFdNum <= MAX_UV_LOOP_BAK_FD, 1);
mcQueBaseMutex.Lock();
mqueUvBase.push(pUvBase);
mcQueBaseMutex.UnLock();
return uv_async_send(&mstUvAsync);
}
int CUvLoop::OnThreadRun() {
ASSERT_RET_VALUE(nullptr != mpUvLoop, 1);
//always run
return uv_run(mpUvLoop, UV_RUN_DEFAULT);
}
如下是uvloop管理功能类
#ifndef __CUvLoopMgr__H_
#define __CUvLoopMgr__H_
#include "singleton.h"
#include "UvLoop.h"
#include <vector>
class CUvLoopMgr : public CSingleton<CUvLoopMgr>{
SINGLE_CLASS_INITIAL(CUvLoopMgr);
public:
~CUvLoopMgr();
public:
int AddUvBase(CUvBase* pUvBase);
private:
std::vector<CUvLoop*> mvecUvLoop;
CUvMutex mcVecUvLoopMuex;
};
#define sUvLoopMgr CUvLoopMgr::Instance()
#endif
#include "UvLoopMgr.h"
CUvLoopMgr::CUvLoopMgr(){
}
CUvLoopMgr::~CUvLoopMgr(){
}
int CUvLoopMgr::AddUvBase(CUvBase* pUvBase) {
ASSERT_RET_VALUE(nullptr != pUvBase, 1);
bool bFlag = false;
mcVecUvLoopMuex.Lock();
for (std::vector<CUvLoop*>::iterator iter = mvecUvLoop.begin(); iter != mvecUvLoop.end(); ++iter) {
CUvLoop* pUvLoop = *iter;
if (nullptr != pUvLoop && pUvLoop->PushUvBase(pUvBase) == 0) {
bFlag = true;
break;
}
}
mcVecUvLoopMuex.UnLock();
if (!bFlag) {
CUvLoop* pUvLoop = new CUvLoop();
if (nullptr != pUvLoop) {
if (0 == pUvLoop->Init()) {
pUvLoop->PushUvBase(pUvBase);
mcVecUvLoopMuex.Lock();
mvecUvLoop.push_back(pUvLoop);
mcVecUvLoopMuex.UnLock();
}else {
DODELETE(pUvLoop);
LOG_ERR("CUvLoop Init Error");
return 1;
}
}else {
LOG_ERR("New UvLoop Error");
return 1;
}
}
return 0;
}