1. 程式人生 > >libuv封裝uvloop自動建立新的loop迴圈

libuv封裝uvloop自動建立新的loop迴圈

#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;
}