[英]Is a queue of lambdas a good design pattern for a work queue in C++11?
我必須創建一個線程安全的工作隊列,它可以在不同的線程中彈出工作,並在工作線程上處理它。 這項工作可能非常通用,所以我在考慮使用帶捕獲的lambdas作為允許這種情況的好方法。 我有以下代碼作為啟動器:
#include <iostream>
#include <vector>
#include <functional>
typedef std::function<void()> Task;
typedef std::vector<Task> TaskQueue;
class Queue
{
public:
void flush() {
for (auto it : m_queue) {
it();
}
}
// will add thread safe locks later.
void queue(Task task) {
m_queue.push_back(task);
}
private:
TaskQueue m_queue;
};
Queue q;
class WorkMaker
{
public:
WorkMaker(int inA) : m_a(inA) {}
void MakeWork() {
q.queue([&]{
std::cout << this->m_a << std::endl;
});
}
private:
int m_a;
};
int main()
{
WorkMaker w1(1);
WorkMaker w2(2);
w1.MakeWork();
w2.MakeWork();
q.flush();
return 0;
}
這段代碼是否存在固有的無法解決的問題,還是編譯器會對其進行優化? 還是通過復制lambda或只是指向它的指針將lambda傳遞給std::function
參數?
編輯:
我想我可以通過使用shared_ptr並將它們傳遞給lambda來解決內存所有權問題。 請考慮以下修改:
typedef std::function<void()> Task;
typedef std::deque<Task> TaskQueue;
class Queue
{
public:
void flush() {
while (!m_queue.empty()) {
auto it = m_queue.front();
m_queue.pop_front();
it();
}
}
// will add thread safe locks later.
void queue(Task task) {
m_queue.push_back(task);
}
private:
TaskQueue m_queue;
};
Queue q;
class WorkMaker : public std::enable_shared_from_this<WorkMaker>
{
public:
WorkMaker(int inA) : m_a(inA) {}
~WorkMaker() { std::cout << "Destroy " << m_a << std::endl; }
void MakeWork() {
std::shared_ptr<WorkMaker> self = shared_from_this();
q.queue([self]{
std::cout << self->m_a << std::endl;
});
}
int m_a;
};
int main()
{
{
auto w1 = std::make_shared<WorkMaker>(1);
auto w2 = std::make_shared<WorkMaker>(2);
w1->MakeWork();
w2->MakeWork();
}
q.flush();
return 0;
}
我得到了所需的輸出:
1
Destroy 1
2
Destory 2
std::function
將創建函數指針,lambda或其引用的任何內容的私有副本。 通常,此副本從std::function
對象引用,以便稍后避免進一步復制。
以這種方式使用std::function
對象沒有什么特別慢的。 但是,你應該考慮用std::deque
替換std::vector
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.