首页 > 编程语言 >C++自用小轮子——线程安全队列

C++自用小轮子——线程安全队列

时间:2024-04-03 12:12:31浏览次数:29  
标签:std return lock C++ queue 自用 线程 data ThreadSafeQueue

目录

简介

记录开发时自用的小轮子:线程安全队列

线程安全队列

#ifndef THREADSAFEQUEUE_H
#define THREADSAFEQUEUE_H

#include <iostream>
#include <queue>
#include <mutex>
#include <condition_variable>
#include <memory>

template<typename T>
class ThreadSafeQueue
{
public:
    ThreadSafeQueue();
    ThreadSafeQueue(const ThreadSafeQueue& other);
    ThreadSafeQueue& operator=(const ThreadSafeQueue& other);
    ~ThreadSafeQueue();
public:
    void push(T new_value);

    //对于pop方法,std::queue中的pop只负责弹出元素,不返回元素
    //这里为了接口简化,设计为在pop的同时返回弹出的元素
    //timeout为超时时间,单位为毫秒
    //默认阻塞pop
    bool wait_and_pop(T& value, std::chrono::milliseconds timeout_millisecond = std::chrono::milliseconds::max());

    std::shared_ptr<T> wait_and_pop(std::chrono::milliseconds timeout_millisecond = std::chrono::milliseconds::max());
    
    bool empty() const;
    size_t size() const;

    T& front();
    const T& front() const;
    std::shared_ptr<T> front_ptr();

private:
    mutable std::mutex mtx;
    std::queue<T> data_queue;
    std::condition_variable data_cond; 
};

template<typename T>
ThreadSafeQueue<T>::ThreadSafeQueue()
{  
}

template<typename T>
ThreadSafeQueue<T>::ThreadSafeQueue(const ThreadSafeQueue& other)
{
    std::lock_guard<std::mutex> lock(other.mtx);
    data_queue = other.data_queue;
}

template<typename T>
ThreadSafeQueue<T>& ThreadSafeQueue<T>::operator=(const ThreadSafeQueue& other)
{
    if (this == &other)
    {
        return *this;
    }
    std::lock(mtx, other.mtx);
    std::lock_guard<std::mutex> self_lock(mtx, std::adopt_lock);
    std::lock_guard<std::mutex> other_lock(other.mtx, std::adopt_lock);
    data_queue = other.data_queue;
    return *this;
}

template<typename T>
ThreadSafeQueue<T>::~ThreadSafeQueue()
{
}

template<typename T>
void ThreadSafeQueue<T>::push(T new_value)
{
    std::lock_guard<std::mutex> lock(mtx);
    data_queue.push(std::move(new_value));
    data_cond.notify_one();
}

template<typename T>
bool ThreadSafeQueue<T>::wait_and_pop(T& value, std::chrono::milliseconds timeout_millisecond)
{
    std::unique_lock<std::mutex> lock(mtx);
    if (data_queue.empty())
    {
        if (timeout_millisecond == std::chrono::milliseconds::max())
        {
            data_cond.wait(lock, [this] {return !data_queue.empty();});
        }
        else
        {
            if (!data_cond.wait_for(lock, timeout_millisecond, [this] {return !data_queue.empty();}))
                return false;
        }
    }
    value = std::move(data_queue.front());
    data_queue.pop();
    return true;
}

template<typename T>
std::shared_ptr<T> ThreadSafeQueue<T>::wait_and_pop(std::chrono::milliseconds timeout_millisecond)
{
    std::unique_lock<std::mutex> lock(mtx);
    if (data_queue.empty())
    {
        if (timeout_millisecond == std::chrono::milliseconds::max())
        {
            data_cond.wait(lock, [this] {return !data_queue.empty();});
        }
        else
        {
            if (!(data_cond.wait_for(lock, timeout_millisecond, [this] {return !data_queue.empty();})))
                return std::shared_ptr<T>();
        }
    }
    std::shared_ptr<T> res(std::make_shared<T>(std::move(data_queue.front())));
    data_queue.pop();
    return res;
}

template<typename T>
bool ThreadSafeQueue<T>::empty() const
{
    std::lock_guard<std::mutex> lock(mtx);
    return data_queue.empty();
}

template<typename T>
size_t ThreadSafeQueue<T>::size() const
{
    std::lock_guard<std::mutex> lock(mtx);
    return data_queue.size();
}

template<typename T>
T& ThreadSafeQueue<T>::front()
{
    std::lock_guard<std::mutex> lock(mtx);
    if(data_queue.empty())
        throw std::runtime_error("queue is empty");
    return data_queue.front();
}

template<typename T>
const T& ThreadSafeQueue<T>::front() const
{
    std::lock_guard<std::mutex> lock(mtx);
    if(data_queue.empty())
        throw std::runtime_error("queue is empty");
    return data_queue.front();
}

template<typename T>
std::shared_ptr<T> ThreadSafeQueue<T>::front_ptr()
{
    std::lock_guard<std::mutex> lock(mtx);
    if(data_queue.empty())
        return std::shared_ptr<T>();
    return std::make_shared<T>(data_queue.front());
}

#endif // THREADSAFEQUEUE_H

标签:std,return,lock,C++,queue,自用,线程,data,ThreadSafeQueue
From: https://www.cnblogs.com/paw5zx/p/18112408

相关文章

  • Rust vs C++:2024,谁更懂错误处理?
    讲动人的故事,写懂人的代码「席双嘉,听说你的C++项目又因为忘了检查返回值导致内存泄漏,又加班了?」周五中午,在国内某科技巨头熙熙攘攘的员工餐厅,贾克强半开玩笑地戳了戳坐在隔壁的席双嘉,眼神中满是戏谑。贾克强,一个热衷于Rust的程序员,总是乐于挑战和探索新技术的边界。而席......
  • c++中译数/数译中
    众所周知,c++中可以输入汉字也可以输出汉字众所不知,rtf文件改后缀为txt时会出一堆奇怪的东西花一节课的时间研究了一下现在有了中译数和数译中的代码可以把txt中的一坨翻译成正常的汉字中译数#include<bits/stdc++.h>usingnamespacestd;voidct(intx){ intx1=x/16......
  • C++内存管理
    内存管理1、C/C++内存分布2、C++动态内存管理方式2.1new和delete2.2operatornew与operatordelete函数2.3定位new3、附录3.1malloc/free和new/delete的区别1、C/C++内存分布intglobalVar=1;staticintstaticGlobalVar=1;voidTest(){staticints......
  • Linux C++ 016-友元
    LinuxC++016-友元本节关键字:Linux、C++、友元及三种实现方式相关库函数:友元的概念及关键字friend在程序里,有些私有属性也可以让类外特殊的函数或者类进行访问,这就需要用到友元技术。友元的目的就是让一个函数或者类访问另一个类中私有成员。友元的三中实现方式(1......
  • Linux C++ 015-对象模型和this指针
    LinuxC++015-对象模型和this指针本节关键字:Linux、C++、对象模型、this指针相关库函数:成员变量和成员函数分开存储1、在C++中,类内的成员变量和成员函数分开存储,只有非静态成员变量才属于类的对象上;2、C++编译器会给每个空对象也分配一个字节的空间,是为了区分空对象占......
  • C++提高学习笔记
    C++提高学习笔记面向对象设计的基本概念面向对象的分析(OOA):解析出需求,需要做什么面向对象的设计(OOD):需要设计哪些类,类中有哪些数据成员,哪些成员函数,类与类之间的关系面向对象的变成(OOP):将需求与设计转换为代码UML语言:同一建模语言类与类之间的关系......
  • C++ 条件与 If 语句:掌握逻辑判断与流程控制精髓
    C++条件和If语句您已经知道C++支持数学中的常见逻辑条件:小于:a<b小于或等于:a<=b大于:a>b大于或等于:a>=b等于:a==b不等于:a!=b您可以使用这些条件来针对不同的决定执行不同的操作。C++具有以下条件语句:使用if来指定一个代码块,如果指定的条件为true,则......
  • 《解释器模式(极简c++)》
            本文章属于专栏-概述-《设计模式(极简c++版)》-CSDN博客模式说明方案:对每个data建立一个单点解释器对象X,dataA和dataB之间的关系,建立一个关系解释器对象Y,这里的Y处理的是X1和X2。这样,复用了解释单文本的逻辑,和多文本间关系的逻辑。优点:灵活性:易于改变......
  • 进程、线程和进程间的通信
    技术笔记!前言一、概念1.程序:存放在磁盘上的指令和数据的有序集合(文件),静态的。2.进程:执行一个程序所分配的资源的总称;进程是程序的一次执行过程;        动态的,包括创建、调度、执行和消亡;3.进程和程序内容区别:BSS段:通常是指用来存放程序中未初始化的......
  • 高精度算法(加、减、乘、除,使用c++实现)
    一、概念在我们进行计算的过程中,经常会遇到几十位,甚至几百位的数字的计算问题,也有可能会遇到小数点后几十位,几百位的情况,而我们面对这样的情况下,  和  的数据范围显然是不够使用的了。因此这时,我们就需要引入一个新的算法,叫做高精度算法。高精度算法:它是处理大数字的数......