首页 > 代码库 > asynDBCenter(不断跟新)

asynDBCenter(不断跟新)

GameServer以前访问DBcenter时同步的,这样服务器都要等待DBcenter返回结果,经理在DBcenter和GameServer之间加了一个asynDBCenter,就实现了异步,感觉还是很复杂,当然经理就20分钟搞定的事,主要函数:

bool asynDBCenter::get_front_and_pop(CmdPkt& pkt)
{
    if(m_queueCmdPkt.empty())
        return false;
    {
        std::unique_lock<std::mutex> lock(m_cmd_mtx);
        pkt = m_queueCmdPkt.front();
        m_queueCmdPkt.pop();
    }
    return true;
}
void asynDBCenter::push_cmd(CmdPkt pkt)
{
    {
        std::unique_lock<std::mutex> cond_lock(m_cond_mtx);//外层就是对应下面的wait操作,这样就实现了线程同步,当有数据时就通知,免得搞个循环判断
        {
            std::unique_lock<std::mutex> cmd_lock(m_cmd_mtx);
            m_queueCmdPkt.push(pkt);
        }
    }
    m_cond.notify_one();//通知threadLoop线程工作
}
void asynDBCenter::push_hr(HrPkt pkt)
{
    std::unique_lock<std::mutex> hr_lock(m_hr_mtx);
    m_queueHrPkt.push(pkt);
}

//------------------------------------------------------------------------------------------------------------------
void asynDBCenter::drive()
{

    HrPkt pkt;
    for (;;)
    {
        if(!m_queueHrPkt.size())
            break ;
        {
            std::unique_lock<std::mutex> hr_lock(m_hr_mtx);
            pkt = m_queueHrPkt.front();
            m_queueHrPkt.pop();
        }
        pkt.process(pkt.on_process, pkt.hr.c_str());                    
    }
}
void asynDBCenter::threadLoop()
{
    while(1) 
    {
        CmdPkt pkt;
        if(get_front_and_pop(pkt))//上了把cmd包的锁,保护包,获取请求cmd包
        {
            pkt.process(pkt.on_process, pkt.json.c_str());//根据cmd请求,访问数据库
            continue;
        }
        {//条件等待
            std::unique_lock<std::mutex> cond_lock(m_cond_mtx);
            m_cond.wait(cond_lock);//有通知时就解锁
        }

    }
}

这里面只要是两个线程共享的变量就需要加锁,也许不加锁,但时间长的话都可能报错。

std::unique_lock<std::mutex> cond_lock(m_cond_mtx);
m_cond.wait(cond_lock);
这个是线程同步的东西,等待其他线程有数据了调用Notify_one就可以唤醒了,wait在阻塞是解锁,在唤醒时锁住,这样都是为了只有一个线程访问公共变量,
内部的各种包都需要同步