STL-queue篇

作者: ninedreams | 来源:发表于2019-10-09 09:08 被阅读0次

    简介

    queue队列是一种先进先出的队列

    用法

    C++队列queue模板类的定义在<queue>头文件中,queue 模板类需要两个模板参数,一个是元素类型,一个容器类型,元素类型是必要的,容器类型是可选的,默认为deque 类型。
    C++队列Queue类成员函数如下:

    back() //返回最后一个元素
    
    empty() //如果队列空则返回真
    
    front() //返回第一个元素
    
    pop() //弹出第一个元素
    
    push() //在末尾加入一个元素
    
    size() //返回队列中元素的个数
    
    emplace() //C++11 原地构造一个元素并插入队列
    
    swap() //C++11 交换内容
    

    成员函数不多,且都简单明了,其中最后两个emplace和swap是C++11中才有的函数。

    简单示例

    #include <queue>
    #include <iostream>
    int main(int argc, char** argv) {
        std::queue<int> q_int;
        q_int.push(1);
        q_int.push(2);
        q_int.push(3);
        std::cout << q_int.front() << " " << q_int.back() << " " << q_int.size() << std::endl;
        q_int.pop();
        std::cout << q_int.front() << " " << q_int.back() << " " << q_int.size() << std::endl;
        return 0;
    }
    

    运行结果如下:


    先从队列尾部加入1 2 3,可以看到队列front()是1,队列back()是3,size()是3。然后使用pop()之后,队列头部就是2了,尾部没有变化还是3,size()也变成了2。

    优先队列priority_queue

    和queue不同的就在于我们可以自定义其中数据的优先级, 让优先级高的排在队列前面,优先出队,函数与队列基本一致。

    top 访问队头元素
    empty 队列是否为空
    size 返回队列内元素个数
    push 插入元素到队尾 (并排序)
    emplace 原地构造一个元素并插入队列
    pop 弹出队头元素
    swap 交换内容
    

    定义:priority_queue<Type, Container, Functional>
    Type 就是数据类型,Container 就是容器类型(Container必须是用数组实现的容器,比如vector,deque等等,但不能用 list,STL里面默认用的是vector),Functional 就是比较的方式,当需要用自定义的数据类型时才需要传入这三个参数,使用基本数据类型时,只需要传入数据类型,默认是大顶堆,列子如下:

    #include<iostream>
    #include <queue>
    using namespace std;
    int main(int argc, char** argv)  {
        //对于基础类型 默认是大顶堆
        priority_queue<int> a;
        //等同于 priority_queue<int, vector<int>, less<int> > a;
    
        //             这里一定要有空格,不然成了右移运算符↓
        priority_queue<int, vector<int>, greater<int> > c;  //这样就是小顶堆
        priority_queue<string> b;
    
        for (int i = 0; i < 5; i++)  {
            a.push(i);
            c.push(i);
        }
        while (!a.empty())  {
            cout << a.top() << ' ';
            a.pop();
        }
        cout << endl;
    
        while (!c.empty())  {
            cout << c.top() << ' ';
            c.pop();
        }
        cout << endl;
    
        b.push("abcd");
        b.push("abcdef");
        b.push("cba");
        while (!b.empty())  {
            cout << b.top() << ' ';
            b.pop();
        }
        cout << endl;
        return 0;
    }
    
    编译出来的结果:

    使用queue实现一个线程安全的redis连接池

    连接池是我们在开发工作中都会用到的一种方法或理念。下面是使用queuemutex实现的一个简单的redis连接池,线程安全。

    #include <queue>
    #include <mutex>
    #include <sstream>
    #include <string>
    #include "hiredis/hiredis.h"
    
    using namesapce std;
    
    class RedisPool {
       private:
        string redis_host;
        int redis_port;
        string auth;
    
        int max;
        int curConnNum;
        queue<redisContext*> redis_queue;
        mutex lock;
    
       private:
        void init();
        redisContext* createConn();
        redisContext* getConn();
        void clear();
        void putConn(redisContext* conn);
    
       public:
        bool redisSendCmd(const string& cmd, string& res);
        bool redisSendCmd(const char* cmd, int len, string& res);
    
       public:
        RedisPool();
        void redisPoolInit(const char* host,
                           const int port,
                           const char* auth,
                           int max = 100);
        ~RedisPool();
    };
    
    RedisPool::RedisPool() {}
    
    RedisPool::~RedisPool() {
        clear();
    }
    
    void RedisPool::redisPoolInit(const char* host,
                                  const int port,
                                  const char* auth,
                                  int max) {
        this->redis_host = host;
        this->redis_port = port;
        this->auth = auth;
        this->max = max;
        init();
    }
    
    redisContext* RedisPool::createConn() {
        redisContext* redis_conn = redisConnect(redis_host.c_str(), redis_port);
        if (redis_conn == NULL || redis_conn->err) {
            if (redis_conn) {
                std::cout << " Redis conn error: " << redis_conn->errstr << std::endl;
            } else {
                std::cout<< " Redis conn error: Can't allocate redis context" << std::endl;
            }
            if (redis_conn != NULL) {
                delete redis_conn;
            }
            return NULL;
        }
        if (auth != "") {
            ostringstream oss;
            oss << "AUTH " << auth;
            redisReply* reply = (redisReply*)redisCommand(redis_conn, oss.str().c_str());
            if (reply == NULL) {
                std::cout << oss.str() << " failed! return NULL";
            }
    
            if (reply->type == REDIS_REPLY_STATUS &&
                strcmp(reply->str, "OK") == 0) {
                freeReplyObject(reply);
            } else {
                std::cout << oss.str() << " failed! return not OK. ret: " << reply->str;
                freeReplyObject(reply);
                delete redis_conn;
                return NULL;
            }
        }
        return redis_conn;
    }
    
    redisContext* RedisPool::getConn() {
        redisContext* c(NULL);
    
        lock.lock();
        while (redis_queue.size() <= 0 && curConnNum >= max) {
            lock.wait();
        }
    
        if (redis_queue.size() > 0) {
            c = redis_queue.front();
            redis_queue.pop();
            lock.unlock();
            // TEST
            // redisReply* reply = redisCommand(c, "PING");
            // if (reply->type == REDIS_REPLY_STRING &&
            //     strcmp(reply->str, "PONG") == 0) {
            //     freeReplyObject(reply);
            //     // OK
            // } else {
            //     freeReplyObject(reply);
            //     // delete
            //     delete c;
            //     c = createConn();
            // }
        } else if (curConnNum < max) {
            lock.unlock();
            c = createConn();
            lock.lock();
            ++curConnNum;
            lock.unlock();
        } else {
            return NULL;
            lock.unlock();
        }
    
        return c;
    }
    
    void RedisPool::putConn(redisContext* conn) {
        lock.lock();
        redis_queue.push(conn);
        lock.signal();
        lock.unlock();
    }
    
    void RedisPool::init() {
        clear();
        curConnNum = 0;
    }
    
    void RedisPool::clear() {
        lock.lock();
        while (!redis_queue.empty()) {
            delete redis_queue.front();
            redis_queue.pop();
        }
        curConnNum = 0;
        lock.unlock();
    }
    
    bool RedisPool::redisSendCmd(const char* cmd, int len, string& res) {
        redisContext* c = nullptr;
        c = getConn();
        if (c == NULL) {
            c = getConn();
            if (c == NULL) {
                return false;
            }
        }
    
        int ret = redisAppendFormattedCommand(c, cmd, len);
        if (ret != REDIS_OK) {
            putConn(c);
            std::cout << "redisAppendFormattedCommand failed! Ret : " << ret << std::endl;
            return false;
        }
    
        redisReply* reply = nullptr;
        if (redisGetReply(c, (void**)&reply) != REDIS_OK) {
            putConn(c);
            LOG(ERROR) << "redisGetReply failed! Ret not REDIS_OK.";
            freeReplyObject(reply);
            return false;
        }
    
        if (reply == nullptr) {
            putConn(c);
            std::cout << "redisGetReply failed! Return reply nullptr." << std::endl;
            freeReplyObject(reply);
            return false;
        }
    
        if (reply->type == REDIS_REPLY_STRING || reply->type == REDIS_REPLY_STATUS) {
            putConn(c);
            res = reply->str;
            freeReplyObject(reply);
            return true;
        }
    
        if (reply->type == REDIS_REPLY_NIL) {
            putConn(c);
            freeReplyObject(reply);
            return false;
        }
    
        putConn(c);
        std::cout << "send redis cmd failed! return not STRING or OK. return type: " << reply->type << ", return str: " << reply->str << std::endl;
        freeReplyObject(reply);
        return false;
    }
    

    相关文章

      网友评论

        本文标题:STL-queue篇

        本文链接:https://www.haomeiwen.com/subject/wlhzlctx.html