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在阻塞是解锁,在唤醒时锁住,这样都是为了只有一个线程访问公共变量,内部的各种包都需要同步