实现了一个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());
}