跳至主要內容

消费者线程的实现

张威大约 2 分钟mysqlmysql连接池

消费者线程的实现

//消费者线程函数,从队列中获取连接
shared_ptr<Connection> ConnectionPool::getConnection() {
    unique_lock<mutex> lock(_queueMutex);
    while(_connectionQue.empty()) {
        cond.wait_for(lock, std::chrono::milliseconds(_connectionTimeout));
        if(_connectionQue.empty()) {
            LOG("获取空闲连接超时了...获取连接失败!");
            return nullptr;
        } 
    }
    
    shared_ptr<Connection> sp(_connectionQue.front());
    _connectionQue.pop();
    if(_connectionQue.empty()) {
        cond.notify_all();
    }
}

再也不被时间束缚:C++ stdchrono时间库全面解析 - 知乎 (zhihu.com)open in new window

重置智能指针析构

shared_ptr<Connection> sp(_connectionQue.front(),
                          [&](Connection *pconn) {
                           // 这里是在服务器应用线程中调用的,所以一定要考虑队列的线程安全操作
                            unique_lock<mutex> lock(_queueMutex);
                            _connectionQue.push(pconn);
                          });

智能指针第二个参数传入函数对象可以重置析构函数,这里使用lambda表达式,但是要注意线程安全问题

wait_for() 优化

wait_for() 返回值是一个类,包含了 timeoutno_timeout

wait_for() 可能会出现这种情况:生产者发出信号,该线程no_timeout退出wait_for() ,但是手慢没有抢到队列中的连接_connectionQue.empty()

    while (_connectionQue.empty())
    {
        if (std::cv_status::timeout == cond.wait_for(lock, std::chrono::milliseconds(_connectionTimeout)))
        {
            if (_connectionQue.empty())
            {
                LOG("获取空闲连接超时了...获取连接失败!");
                return nullptr;
            }
        }
    }

最终版 消费者线程处理函数

// 消费者线程函数,从队列中获取连接
shared_ptr<Connection> ConnectionPool::getConnection()
{
    unique_lock<mutex> lock(_queueMutex);
    while (_connectionQue.empty())
    {
        if (std::cv_status::timeout == cond.wait_for(lock, std::chrono::milliseconds(_connectionTimeout)))
        {
            if (_connectionQue.empty())
            {
                LOG("获取空闲连接超时了...获取连接失败!");
                return nullptr;
            }
        }
    }

    /*
    shared_ptr智能指针析构时,会把connection资源直接delete掉,相当于
    调用connection的析构函数,connection就被close掉了。
    这里需要自定义shared_ptr的释放资源的方式,把connection直接归还到queue当中
    */
    shared_ptr<Connection> sp(_connectionQue.front(),
                              [&](Connection *pconn)
                              {
                                  // 这里是在服务器应用线程中调用的,所以一定要考虑队列的线程安全操作
                                  unique_lock<mutex> lock(_queueMutex);
                                  _connectionQue.push(pconn);
                              });
    _connectionQue.pop();
    if (_connectionQue.empty())
    {
        cond.notify_all();
    }
}