而不是產卵每個任務一個新的線程,爲什麼不只是形成了幾個工作線程,然後使用std:packaged_task
和std::future
併發計算的東西,而不產生一個新的線程的開銷
例如:
class Calculator {
public:
Calculator() : m_bDoneFlag(false) {
for(auto& thread : m_arrayThreads)
{
thread = std::thread([this]{
std::unique_lock<std::mutex> lockGuard(m_mutex, std::defer_lock);
while(!m_bDoneFlag)
{
lockGuard.lock();
m_condTaskWaiting.wait(lockGuard, [this]{ return !m_queueTasks.empty(); });
std::packaged_task<void*()> packagedTask = std::move(m_queueTasks.front());
m_queueTasks.pop();
lockGuard.unlock();
// Execute task:
packagedTask();
}
});
}
}
~Calculator()
{
m_bDoneFlag = true;
std::unique_lock<std::mutex> lockGuard(m_mutex);
m_queueTasks.emplace([]{ std::this_thread::sleep_for(std::chrono::milliseconds(100)); return nullptr; });
m_queueTasks.emplace([]{ std::this_thread::sleep_for(std::chrono::milliseconds(100)); return nullptr; });
lockGuard.unlock();
m_condTaskWaiting.notify_all();
for(auto& thread : m_arrayThreads)
{
thread.join();
}
}
std::future<void*> AddTask(std::function<void*()> funcToAdd)
{
std::packaged_task<void*()> packagedTask(funcToAdd);
std::future<void*> future = packagedTask.get_future();
std::unique_lock<std::mutex> lockGuard(m_mutex);
m_queueTasks.emplace(std::move(packagedTask));
lockGuard.unlock();
m_condTaskWaiting.notify_one();
return future;
}
private:
std::mutex m_mutex;
std::array<std::thread, 2> m_arrayThreads;
std::queue<std::packaged_task<void*()>> m_queueTasks;
std::condition_variable m_condTaskWaiting;
std::atomic<bool> m_bDoneFlag;
};
然後,您可以使用此像這樣:
int main()
{
Calculator myCalc;
std::future<void*> future1 = myCalc.AddTask([]{ std::string* pszTest = new std::string("Test String"); return pszTest; });
std::future<void*> future2 = myCalc.AddTask([]{ std::complex<float>* pcmplxTest = new std::complex<float>(5.0f, 10.5f); return pcmplxTest; });
std::string* pszTest = reinterpret_cast<std::string*>(future1.get());
std::complex<float>* pcmplxTest = reinterpret_cast<std::complex<float>*>(future2.get());
std::cout << *pszTest << " and " << *pcmplxTest << std::endl;
delete pszTest;
delete pcmplxTest;
return 0;
}
顯然,這並不具備類型安全,我們會想,你可以改善型安全顯著如果您可以縮小返回類型值,您將始終需要防止必須返回指向void
的指針。
沒有鎖定,如果此代碼將在同一時間調用兩次,則可能創建2個線程。 如果你只從一個特定的線程調用它,這不是一個問題。 – asafrob
std :: invokeWhenLastDoneWhatExactly? –