C++11线程安全队列实现

实现了一个C++11线程安全队列,可以作为模板使用。

#include <functional>
#include <iostream>
#include <memory>
#include <mutex>
#include <thread>
#include<vector>
#include <condition_variable>

template <typename T>
class threadsafe_queue {
private:
    struct node { // 存储了数据和下一个节点指针的节点
        std::shared_ptr<T> data;
        std::unique_ptr<node> next;
    };

    std::mutex head_mutex; // 头指针互斥锁
    std::unique_ptr<node> head; // 头指针
    std::mutex tail_mutex; //
    node *tail; // 尾指针
    std::condition_variable data_cond;
    node* get_tail() { // 获取尾部节点指针
        std::lock_guard<std::mutex> tail_lock(tail_mutex);
        return tail;
    }
    // pop头结点
    std::unique_ptr<node> pop_head() {
        auto old_head = std::move(head);
        head = std::move(old_head->next);
        return old_head;
    }
    // 线程等待消息队列数据,获取锁
    std::unique_lock<std::mutex> wait_for_data() {
        std::unique_lock<std::mutex> head_lock(head_mutex);
        data_cond.wait(head_mutex, [&]{return head.get() != get_tail();}); // 队列不为空
        return std::move(head_lock);
    }
    // 等待锁并pop头部节点
    std::unique_ptr<node> wait_pop_head() {
        std::unique_lock<std::mutex> head_lock(wait_for_data());
        return pop_head();
    }
    // 等待锁并pop头部节点,拿到数据
    std::unique_ptr<node> wait_pop_head(T& value) {
        std::unique_lock<std::mutex> head_lock(wait_for_data());
        value = std::move(*head->data);
        return pop_head();
    }
    // 尝试pop头结点
    std::unique_ptr<node> try_pop_head() {
        std::lock_guard<std::mutex> head_lock(head_mutex);
        if (head->get() == get_tail()) {
            return std::unique_ptr<node>(); // 队列空返回空节点
        }
        return pop_head();
    }

    std::unique_ptr<node> try_pop_head(T& value) {
        std::lock_guard<std::mutex> head_lock(head_mutex);
        if (head.get() == get_tail()) {
            return std::unique_ptr<node>();
        }
        value = std::move(*head->data);
        return pop_head();
    }

public:
    threadsafe_queue(): head(new node), tail(head.get()){}
    threadsafe_queue(const threadsafe_queue& other) = delete;
    threadsafe_queue& operator=(const threadsafe_queue& other) = delete;
    std::shared_ptr<T> try_pop();
    bool try_pop(T& value);
    std::shared_ptr<T> wait_and_pop();
    void wait_and_pop(T& value);
    void push(T new_value);
    bool empty();

};

template<typename T>
void threadsafe_queue<T>::push(T new_value) { // 消息入队
    std::shared_ptr<T> new_data(std::make_shared<T>(std::move(new_value))); // 构建新数据
    std::unique_ptr<node> p(new node); // 新尾节点
    {
        std::lock_guard<std::mutex> tail_lock(tail_mutex);
        tail->data = new_data; // 数据给到tail
        node* const new_tail = p.get();
        tail->next = std::move(p); // next节点给到tail
        tail = new_tail;
    }
    data_cond.notify_all(); // 提醒线程拿数据
}
// 等待并pop头结点
template<typename T>
shared_ptr<T> threadsafe_queue<T>::wait_and_pop() {
    auto const old_head = wait_pop_head();
    return old_head->data;
}

// 等待并pop头结点
template<typename T>
void threadsafe_queue<T>::wait_and_pop(T &value) {
    wait_pop_head(value);
}
// 尝试pop头结点
template<typename T>
shared_ptr<T> threadsafe_queue<T>::try_pop() {
    auto old_head = try_pop_head();
    return old_head ? old_head->data : std::shared_ptr<T>();
}
// 尝试pop头结点
template<typename T>
bool threadsafe_queue<T>::try_pop(T &value) {
    auto old_head = try_pop_head(value);
    return old_head;
}
// 判空
template<typename T>
bool threadsafe_queue<T>::empty() {
    std::lock_guard<std::mutex> head_lock(head_mutex);
    return (head.get() == get_tail());
}

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值