首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >CPP:这是进行线程安全FIFIO消息队列的合理方法吗?

CPP:这是进行线程安全FIFIO消息队列的合理方法吗?
EN

Stack Overflow用户
提问于 2022-01-09 18:30:28
回答 1查看 411关注 0票数 0

请温柔点-我第一次在这里发帖。现在教我自己C++。想玩线程和在它们之间传递任何类型的消息。还没有到线程部分--只是处理消息队列元素。下面是我放在一起的代码,至少在一个main()线程中是这样的。在我开始创建自定义数据对象和线程函数之前--如果我到目前为止所做的工作是可行的(如果不是完全符合约定/标准或完全有效的话),我想要获得一个共识--因此,如果这样做会在以后的线程中造成不必要的复杂性,那么我只是在寻找方向。

所以有两个代码文件:

messageQueue.h包括实现和头,因为无法使链接器与实现一起工作在一个单独的cpp文件中。

代码语言:javascript
运行
复制
#pragma once
#include<queue>         // for queue
#include<thread>        // for smart pointers
#include<mutex>         // for locking of the queue when doing push(), front() and pop()



/*
Purpose:
To provide a thread safe method of of passing messages between threads in a FIFO queue manner.
Currently this uses unique_ptr which enables a one to one publisher/consumer application, if
we need one to many publisher/consumer model then will need to investigate maintaining a collection 
of subscribers (consumers) and use shared_ptr.
Usage notes:
Message objects need to be created using make_unique not using new - e.g.
    auto messagePtr = std::make_unique<message_t<std::string>>("this is a message");
Call this way: 
    messageQueue<objectType> messageQueueName;
    messageQueueName.publish(std::move(messagePtr));
    messagePtr = messageQueueName.consume();
*/

template<class T>
class message_t
{
public:
    message_t(T message) : m_message{ message } {}

private:
    T m_message;
};

template<class T>
class messageQueue
{
public:
    messageQueue() {};
    void publish(std::unique_ptr<message_t<T>> messagePtr);
    std::unique_ptr<message_t<T>> consume();
    bool hasData();
private:
    std::queue < std::unique_ptr<message_t<T>>> m_queue;
    std::mutex m_mutex;

};

// Had to add the implementation into the header file as templated classes have link issues when in separate cpp files :-(

template<class T>
void messageQueue<T>::publish(std::unique_ptr<message_t<T>> messagePtr) {
    std::lock_guard<std::mutex> lock(m_mutex); 
    m_queue.push(std::move(messagePtr));
};

template<class T>
std::unique_ptr<message_t<T>> messageQueue<T>::consume() {
    std::unique_ptr<message_t<T>> retVal;
    {
        std::lock_guard<std::mutex> lock(m_mutex);
        if (!m_queue.empty()) { retVal = std::move(m_queue.front()); }
        m_queue.pop();
    }

    return retVal;
};

template<class T>
bool messageQueue<T>::hasData() {
    std::lock_guard<std::mutex> lock(m_mutex);
    return(!m_queue.empty());
};

main.cpp --其中只有一个非常简单的测试用例。

代码语言:javascript
运行
复制
#include "messageQueue.h"
#include<string>
#include<iostream>


int main(void) {
    messageQueue<std::string> textQueue;                        // Create the message queue 
    auto messagePtr = std::make_unique<message_t<std::string>>("this is a message");    // Create a message and get its unique pointer
    std::cout << "messagePtr= " << messagePtr << std::endl;     // output the pointer value
    textQueue.publish(std::move(messagePtr));                   // Push the message pointer onto the queue : messagePtr is now 0
    auto newMessagePtr = std::make_unique<message_t<std::string>>("this is another message");   // Create a second message and get its unique pointer
    std::cout << "newMessagePtr= " << newMessagePtr << std::endl;   // output the new message pointer value
    std::cout << "Consuming messagePtr into newMessagePtr" << std::endl;    //comment
    if (textQueue.hasData()) { newMessagePtr = textQueue.consume(); }   // Pull the original pointer off the queue and assign to new message pointer
    std::cout << "newMessagePtr= " << newMessagePtr << std::endl;   // output the pointer in the new message pointer - should be first pointer value


    return(0);
}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-01-09 18:46:06

我看到的一个问题是,如果消息队列是空的,那么仍然会弹出消息队列。

还有一个概念上的问题:在多线程环境中,hasData()是没有意义的。无论它返回什么,它都可能被另一个线程立即失效。因此,任何代码都不能真正依赖于返回值,除非您接受其正确性的不确定性。

更常见的方法是简单地无条件地try_consume值(如果没有消息,则返回nullptr )--基本上已经实现为consume

另一种方法是有一个阻塞的consume,它停止当前线程直到其他线程写入队列。然而,这需要使用信令,例如通过std::condition_variable或atomics。这有它的缺陷,但如果你正在学习,花时间去了解它是如何工作的是值得的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70644281

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档