zoukankan      html  css  js  c++  java
  • asynDBcenter(复习)

    asynDBCenter
    asynDBCenter是GS和DBCenter之间的模块,有了他GS访问数据库就是异步的了,以前是同步的,加入某个操作很耗时那么GS就在那等待这个返回值。
    1.对于std::queue哪些情况要加锁,哪些不加
    push、pop操作100%必须加锁,front和back操作是只读的,不会破坏状态,但是有读写顺序要求时还是要同步。
    一般empty和size就不要锁了,对于锁
    
    里面有两个容器
        std::queue<CmdPkt> m_queueCmdPkt;//命令包容器
        std::queue<HrPkt> m_queueHrPkt;//相应包容器
    
    2.m_queueCmdPkt这个容器是什么时候放入的呢?
    玩家登录获取userid的函数
    /*
    std::condition_variable
    进入时获得锁,wait时释放,当别人通知的时候重新获得
    锁的状态在线程阻塞之前和阻塞之后相同
    */
    void asynDBCenter::push_cmd(CmdPkt pkt)
    {
        {
            std::unique_lock<std::mutex> cond_lock(m_cond_mtx);//这里加锁,主要还是同步,但没有多大意义,因为没有对公共的变量操作,不是很确定
            {
                std::unique_lock<std::mutex> cmd_lock(m_cmd_mtx);
                m_queueCmdPkt.push(pkt);
            }
        }
        m_cond.notify_one();//取的线程阻塞了,现在通知
    }
    
    
    void asynDBCenter::getUserID(std::function<void(int hr)>* on_getUserID, char* userName)
    {
        boost::property_tree::ptree pt;
        pt.put("userName", userName);
        std::stringstream os;
        boost::property_tree::write_json(os, pt);
        
        CmdPkt pkt;
        pkt.json = os.str();
        pkt.process = std::bind(&asynDBCenter::isGetUserID, this, ph::_1, ph::_2);
        pkt.on_process = (void*)on_getUserID;
        push_cmd(pkt);//此时放入
    }
    
    3.什么时候从m_queueCmdPkt容器获取
    asynDBCenter::asynDBCenter()
    {
        m_dbcenter.reset(NEW(DBCenter));
        m_spThread.reset(new std::thread(std::bind(&asynDBCenter::threadLoop, this)));
    }
    
    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::threadLoop()
    {
        while(1) 
        {
            CmdPkt pkt;
            if(get_front_and_pop(pkt))
            {
                pkt.process(pkt.on_process, pkt.json.c_str());//访问数据库
                continue;
            }
            {//表示GS发过来的命令没有了
                std::unique_lock<std::mutex> cond_lock(m_cond_mtx);
                m_cond.wait(cond_lock);//使用unique_lock锁住当前线程,然后另一个线程在相同的m_cond上调用notify时此线程才会解除阻塞
            }
        }
    }
    
    4.访问数据库
    
    void asynDBCenter::push_hr(HrPkt pkt)
    {
        std::unique_lock<std::mutex> hr_lock(m_hr_mtx);
        m_queueHrPkt.push(pkt);//直接放入
    }
    
    void asynDBCenter::isGetUserID(void* on_process, const char* arg)
    {
        std::stringstream ros(arg);
        boost::property_tree::ptree pt;
        boost::property_tree::read_json(ros, pt);
        std::string userName = pt.get<std::string>("userName");
    
        int ret = m_dbcenter->getUserID(const_cast<char*>(userName.c_str()));
    
        boost::property_tree::ptree ret_pt;//将数据库返回的值封装成json
        ret_pt.put("userID", ret);
        std::stringstream wos;
        boost::property_tree::write_json(wos, ret_pt);
        //放到结果包里面去
        HrPkt pkt;
        pkt.hr = wos.str();
        pkt.on_process = on_process;
        pkt.process = std::bind(&asynDBCenter::onGetUserID, this, ph::_1, ph::_2);
        push_hr(pkt);
    }
    
    5.函数回调
    void asynDBCenter::drive()
    {
    
        HrPkt pkt;
        for (;;)
        {
            if(!m_queueHrPkt.size())//drive一下就把m_queueHrPkt所有的命令都执行了
                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(), pkt.len);                    
        }
    }
    
    for (;;)
    {
        procMapSendData();//test1
    
        m_asyndb->drive();//这个是在gs里面drive的
    
        bool hr = process_loop(pkt);
        procMapSendData();
        //......
    }
    GS线程发命令到asyn,asyn线程去访问数据库,然后GS线程去驱动,然后回调GS里面的函数
    function在这里面起了很大的作用
  • 相关阅读:
    Spark学习笔记——安装和WordCount
    Scala学习笔记——入门
    Scala学习笔记——安装
    Maven常用命令(转)
    maven中snapshot快照库和release发布库的区别和作用 (转)
    Hadoop学习笔记——WordCount
    Hadoop学习笔记——安装Hadoop
    机器学习——利用SVD简化数据
    Python自然语言处理学习——jieba分词
    机器学习——大数据与MapReduce
  • 原文地址:https://www.cnblogs.com/zzyoucan/p/3991740.html
Copyright © 2011-2022 走看看