請保持溫和 - 我第一次在這里發帖。目前自學C 。想玩執行緒并在它們之間傳遞任何型別的訊息。還沒有進入執行緒部分 - 只是處理訊息佇列元素。下面是我放在一起的代碼 - 至少在一個 main() 執行緒中。在我開始創建自定義資料物件和執行緒函式之前——我想就我到目前為止所做的事情是否可行(如果不完全符合約定/標準或完全有效)達成共識——所以如果這是真的只是在尋找方向稍后將使用執行緒創建不必要的復雜性。
所以兩個代碼檔案:
messageQueue.h包括實作以及標頭,因為無法使聯結器與位于單獨的 cpp 檔案中的實作一起作業。
#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 - 里面只有一個非常簡單的測驗用例。
#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);
}
uj5u.com熱心網友回復:
我看到的一個問題是,如果訊息佇列為空,您仍然會從中彈出。
還有一個概念性問題:在多執行緒環境hasData()中永遠沒有意義。無論它回傳什么,它都可能立即被另一個執行緒無效。因此,除非您接受其正確性的不確定性,否則任何代碼都不能真正依賴于回傳值。
更常見的方法是try_consume無條件地簡單地設定值(如果沒有訊息,則回傳 nullptr)-您基本上已經將其實作為consume.
另一種方法是使用阻塞consume,它會暫停當前執行緒,直到其他執行緒寫入佇列。然而,這需要使用信令,例如通過std::condition_variable或原子。這有其陷阱,但如果您正在學習,值得花時間了解它的作業原理。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/407747.html
標籤:
上一篇:缺少Default.aspx表單
下一篇:C 20模塊匯出模板實體化
