线程安全队列

博客内容包含线程安全队列头文件 thread_safe_queue.h 和测试文件 test.c,涉及信息技术领域的代码文件相关内容。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

// thread_safe_queue.h

#ifndef THREAD_SAFE_QUEUE_H
#define THREAD_SAFE_QUEUE_H

#include <string>
#include <memory>
#include <mutex>
#include <atomic>
#include <sstream>
#include <iostream>
#include <condition_variable>

template<typename T>
class ThreadSafeQueue {
    private:
        struct node {
            std::shared_ptr<T> data;
            std::shared_ptr<node> next;
        };

        std::mutex head_mutex_;
        std::shared_ptr<node> head_;
        std::mutex tail_mutex_;
        std::shared_ptr<node> tail_;
        std::condition_variable data_cond_;
        std::atomic<int> size_;

    public:
        ThreadSafeQueue(): head_(new node), tail_(head_), size_(0) {}
        ThreadSafeQueue(const ThreadSafeQueue& other) = delete;
        ThreadSafeQueue& operator=(const ThreadSafeQueue& other) = delete;

        bool empty();
        void push(T new_value);
        void push(std::shared_ptr<T> new_value_ptr);
        bool try_pop(T& value);
        std::shared_ptr<T> try_pop();
        bool wait_and_pop(T& value);
        std::shared_ptr<T> wait_and_pop();

        int size() {return size_; };
        std::string debug_info();

    private:
        std::shared_ptr<node> get_tail() {
            std::lock_guard<std::mutex> tail_lock(tail_mutex_);
            return tail_;
        }
        std::shared_ptr<node> pop_head() {
            std::shared_ptr<node> old_head = head_;
            head_ = old_head->next;
            size_--;
            return old_head;
        }
        std::unique_lock<std::mutex> wait_for_data() {
            std::unique_lock<std::mutex> head_lock(head_mutex_);
            data_cond_.wait(head_lock, [&]{return head_!=get_tail();});
            return std::move(head_lock);
        }
        std::shared_ptr<node> wait_pop_head() {
            std::unique_lock<std::mutex> head_lock(wait_for_data());
            return pop_head();
        }
        std::shared_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();
        }
        std::shared_ptr<node> try_pop_head() {
            std::lock_guard<std::mutex> head_lock(head_mutex_);
            if (head_ == get_tail()) {
                return std::shared_ptr<node>();
            }
            return pop_head();
        }
        std::shared_ptr<node> try_pop_head(T& value) {
            std::lock_guard<std::mutex> head_lock(head_mutex_);
            if (head_ == get_tail()) {
                return std::shared_ptr<node>();
            }
            value = std::move(*head_->data);
            return pop_head();
        }
};

template<typename T>
bool ThreadSafeQueue<T>::empty() {
    std::lock_guard<std::mutex> head_lock(head_mutex_);
    return (head_==get_tail());
}

template<typename T>
void ThreadSafeQueue<T>::push(T new_value) {
    std::shared_ptr<T> new_data(std::make_shared<T>(std::move(new_value)));
    push(new_data);
}

template<typename T>
void ThreadSafeQueue<T>::push(std::shared_ptr<T> new_data) {
    std::shared_ptr<node> new_tail(new node);
    {
        std::lock_guard<std::mutex> tail_lock(tail_mutex_);
        tail_->data = new_data;
        tail_->next = new_tail;
        tail_ = new_tail;
        size_++;
    }
    data_cond_.notify_one();
}

template<typename T>
bool ThreadSafeQueue<T>::try_pop(T& value) {
    std::shared_ptr<node> old_head = try_pop_head(value);
    return old_head;
}

template<typename T>
std::shared_ptr<T> ThreadSafeQueue<T>::try_pop() {
    std::shared_ptr<node> old_head = try_pop_head();
    return old_head? old_head->data: std::shared_ptr<T>();
}

template<typename T>
bool ThreadSafeQueue<T>::wait_and_pop(T& value) {
    std::shared_ptr<node> const old_head = wait_pop_head(value);
}

template<typename T>
std::shared_ptr<T> ThreadSafeQueue<T>::wait_and_pop() {
    std::shared_ptr<node> const old_head = wait_pop_head();
    return old_head->data;
}

template<typename T>
std::string ThreadSafeQueue<T>::debug_info() {
    std::ostringstream oss;
    std::unique_lock<std::mutex> lock_head(head_mutex_, std::defer_lock);
    std::unique_lock<std::mutex> lock_tail(tail_mutex_, std::defer_lock);
    std::lock(lock_head, lock_tail);

    std::shared_ptr<node> p = head_;
    int num = 0;
    int num_limit = 100;
    bool cross_limit = false;
    oss << "size[" << size() << "]  ";
    oss  << "[head] -> ";
    while (p && p->data) {
        if (++num <= num_limit) {
            oss << *p->data << " -> ";
            if (num % 20 == 0) {
                oss << std::endl;
            }
        } else {
            if (!cross_limit) {
                cross_limit = true;
                oss << "... ..." << " -> ";
            }
        }
        p = p->next;
    }
    oss << "[tail]" << "  [" << num << "]";
    if (num != size()) {
        oss << " [error: num do not match size]";
    }

    return oss.str();
}

#endif /* THREAD_SAFE_QUEUE_H */

// test.c

#include "thread_safe_queue.h"

int main() {
    ThreadSafeQueue<std::string> myQueue;
    myQueue.push("001");
    std::cout << myQueue.debug_info() << std::endl;
    myQueue.push("002");
    std::cout << myQueue.debug_info() << std::endl;
    myQueue.push("003");
    std::cout << myQueue.debug_info() << std::endl;
    myQueue.push("004");
    std::cout << myQueue.debug_info() << std::endl;
    myQueue.push("005");
    std::cout << myQueue.debug_info() << std::endl;
    myQueue.push("006");
    std::cout << myQueue.debug_info() << std::endl;
    myQueue.push("007");
    std::cout << myQueue.debug_info() << std::endl;
    myQueue.push("008");
    std::cout << myQueue.debug_info() << std::endl;
    myQueue.push("009");
    std::cout << myQueue.debug_info() << std::endl;
    myQueue.push("010");
    std::cout << myQueue.debug_info() << std::endl;
    myQueue.wait_and_pop();
    std::cout << myQueue.debug_info() << std::endl;
    myQueue.wait_and_pop();
    std::cout << myQueue.debug_info() << std::endl;
    myQueue.wait_and_pop();
    std::cout << myQueue.debug_info() << std::endl;
    myQueue.wait_and_pop();
    std::cout << myQueue.debug_info() << std::endl;
    myQueue.wait_and_pop();
    std::cout << myQueue.debug_info() << std::endl;
    myQueue.wait_and_pop();
    std::cout << myQueue.debug_info() << std::endl;
    myQueue.wait_and_pop();
    std::cout << myQueue.debug_info() << std::endl;
    myQueue.wait_and_pop();
    std::cout << myQueue.debug_info() << std::endl;
    myQueue.try_pop();
    std::cout << myQueue.debug_info() << std::endl;
    myQueue.wait_and_pop();
    std::cout << myQueue.debug_info() << std::endl;
    myQueue.try_pop();
    std::cout << myQueue.debug_info() << std::endl;
    myQueue.try_pop();
    std::cout << myQueue.debug_info() << std::endl;
    myQueue.try_pop();
    std::cout << myQueue.debug_info() << std::endl;
    return 0;
}
$ g++ test.cpp -o test && ./test
size[1]  [head] -> 001 -> [tail]  [1]
size[2]  [head] -> 001 -> 002 -> [tail]  [2]
size[3]  [head] -> 001 -> 002 -> 003 -> [tail]  [3]
size[4]  [head] -> 001 -> 002 -> 003 -> 004 -> [tail]  [4]
size[5]  [head] -> 001 -> 002 -> 003 -> 004 -> 005 -> [tail]  [5]
size[6]  [head] -> 001 -> 002 -> 003 -> 004 -> 005 -> 006 -> [tail]  [6]
size[7]  [head] -> 001 -> 002 -> 003 -> 004 -> 005 -> 006 -> 007 -> [tail]  [7]
size[8]  [head] -> 001 -> 002 -> 003 -> 004 -> 005 -> 006 -> 007 -> 008 -> [tail]  [8]
size[9]  [head] -> 001 -> 002 -> 003 -> 004 -> 005 -> 006 -> 007 -> 008 -> 009 -> [tail]  [9]
size[10]  [head] -> 001 -> 002 -> 003 -> 004 -> 005 -> 006 -> 007 -> 008 -> 009 -> 010 -> [tail]  [10]
size[9]  [head] -> 002 -> 003 -> 004 -> 005 -> 006 -> 007 -> 008 -> 009 -> 010 -> [tail]  [9]
size[8]  [head] -> 003 -> 004 -> 005 -> 006 -> 007 -> 008 -> 009 -> 010 -> [tail]  [8]
size[7]  [head] -> 004 -> 005 -> 006 -> 007 -> 008 -> 009 -> 010 -> [tail]  [7]
size[6]  [head] -> 005 -> 006 -> 007 -> 008 -> 009 -> 010 -> [tail]  [6]
size[5]  [head] -> 006 -> 007 -> 008 -> 009 -> 010 -> [tail]  [5]
size[4]  [head] -> 007 -> 008 -> 009 -> 010 -> [tail]  [4]
size[3]  [head] -> 008 -> 009 -> 010 -> [tail]  [3]
size[2]  [head] -> 009 -> 010 -> [tail]  [2]
size[1]  [head] -> 010 -> [tail]  [1]
size[0]  [head] -> [tail]  [0]
size[0]  [head] -> [tail]  [0]
size[0]  [head] -> [tail]  [0]
size[0]  [head] -> [tail]  [0]

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值