队列

#include <iostream>
#include <mutex>
#include <condition_variable>
#include <thread>

template<typename T> 
class ThreadSafeQueue {
private:  
    struct Node {  
        std::shared_ptr<T> p_data; //指向数据块
        std::unique_ptr<Node> next;
    }; 
    std::unique_ptr<Node> head;//头
    Node* tail;  //尾
    mutable std::mutex mtx_head; 
    mutable std::mutex mtx_tail;
    std::condition_variable con_push; //数据入队通知

public:
    ThreadSafeQueue():head(new Node),tail(head.get()) {}
    ~ThreadSafeQueue() {
        while(head){
            head = std::move(head->next);
        }
        tail = nullptr;
    }
    ThreadSafeQueue(const ThreadSafeQueue&)=delete;
    ThreadSafeQueue& operator=(const ThreadSafeQueue&)=delete;

private:
    Node* get_tail() {
        std::lock_guard<std::mutex> lock_tail(mtx_tail);
        return tail;
    }
  
    std::unique_ptr<Node> pop_head()
    {
        std::unique_ptr<Node> old_head=std::move(head);
        head=std::move(old_head->next);
        return old_head;
    }
  
    std::unique_ptr<Node> try_pop_head(T& value)
    {
        std::lock_guard<std::mutex> head_lock(mtx_head);
        if(head.get()==get_tail())
        {
            return std::unique_ptr<Node>();
        }
        value=std::move(*head->p_data);
        return pop_head();
    }
  
    std::unique_ptr<Node> wait_pop_head(T& value)
    {
        std::unique_lock<std::mutex> head_lock(mtx_head);
        con_push.wait(head_lock,[&]{return head.get()!=get_tail();});
        value=*head->p_data;
        return pop_head();
    }

public:
    void push(T value) { 
        //构造数据块
        std::shared_ptr<T> new_data(std::make_shared<T>(value));
        //构造新节点
        std::unique_ptr<Node> new_node(new Node); //会被当做新的虚拟节点
        {
            //操作尾部指针,先加锁
            std::lock_guard<std::mutex> tail_lock(mtx_tail);
            tail->p_data = new_data; //数据块挂载
            tail->next = std::move(new_node); 
            tail = (tail->next).get();//指向新的虚拟节点
        }
        con_push.notify_one();  
    }
    
    bool try_pop(T& value) {
        std::unique_ptr<Node> const old_head=try_pop_head(value);
        return old_head != nullptr;        
    }
    
    void wait_and_pop(T& value)
    {
        std::unique_ptr<Node> const old_head=wait_pop_head(value);
    }
};

void producer(ThreadSafeQueue<int>& queue, int n) {
    for (int i = 0; i < n; ++i) {
        std::this_thread::sleep_for(std::chrono::milliseconds(50)); // 模拟生产过程中的延迟
        queue.push(i);
        std::cout << "Produced: " << i << std::endl;
    }
}

void consumer_try_pop(ThreadSafeQueue<int>& queue, int n) {
    for (int i = 0; i < n; ++i) {
        int value;
        if (queue.try_pop(value)) {
            std::cout << "Consumer (try_pop): " << value << std::endl;
        } else {
            std::cout << "Queue is empty" << std::endl;
        }
        std::this_thread::sleep_for(std::chrono::milliseconds(200)); // 模拟消费过程中的延迟
    }
}

void consumer_wait_and_pop(ThreadSafeQueue<int>& queue, int n) {
    for (int i = 0; i < n; ++i) {
        int value;
        queue.wait_and_pop(value);
        std::cout << "Consumer (wait_and_pop): " << value << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(200)); // 模拟消费过程中的延迟
    }
}

int main() {
    ThreadSafeQueue<int> queue;

    const int num_produce = 100;
    const int num_consume = 25;

    std::thread producer_thread1(producer, std::ref(queue), num_produce);
    //std::thread consumer_try_pop_thread1(consumer_try_pop, std::ref(queue), num_consume);
    //std::thread consumer_try_pop_thread2(consumer_try_pop, std::ref(queue), num_consume);
    std::thread consumer_wait_and_pop_thread1(consumer_wait_and_pop, std::ref(queue), num_consume);
    std::thread consumer_wait_and_pop_thread2(consumer_wait_and_pop, std::ref(queue), num_consume);
    std::thread consumer_wait_and_pop_thread3(consumer_wait_and_pop, std::ref(queue), num_consume);
    std::thread consumer_wait_and_pop_thread4(consumer_wait_and_pop, std::ref(queue), num_consume);
    
    producer_thread1.join();
    //consumer_try_pop_thread1.join();
    //consumer_try_pop_thread2.join();
    consumer_wait_and_pop_thread1.join();
    consumer_wait_and_pop_thread2.join();
    consumer_wait_and_pop_thread3.join();
    consumer_wait_and_pop_thread4.join();    
    return 0;
}

  

posted @ 2024-04-02 16:18  fchy822  阅读(2)  评论(0编辑  收藏  举报