11 #ifndef smtk_common_ThreadPool_h
12 #define smtk_common_ThreadPool_h
14 #include "smtk/common/CompilerInformation.h"
18 #include <condition_variable>
24 #include <type_traits>
35 template<
typename ReturnType =
void>
39 std::is_same<ReturnType, void>::value || std::is_default_constructible<ReturnType>::value,
40 "Templated return type must be void or a default constructible type");
50 template<
typename Function,
typename... Types>
51 std::future<ReturnType>
operator()(Function&&
function, Types&&... args)
53 return appendToQueue(std::bind(
function, std::forward<Types>(args)...));
61 std::future<ReturnType> appendToQueue(std::function<ReturnType()>&& task);
69 std::condition_variable m_condition;
70 std::mutex m_queueMutex;
71 std::vector<std::thread> m_threads;
72 std::queue<std::packaged_task<ReturnType()>> m_queue;
73 bool m_initialized{
false };
74 std::atomic<bool> m_active;
75 unsigned int m_maxThreads;
78 template<
typename ReturnType>
81 , m_maxThreads(maxThreads == 0 ? std::thread::hardware_concurrency() : maxThreads)
85 template<
typename ReturnType>
94 for (std::size_t i = 0; i < m_threads.size(); i++)
96 (*this)([] {
return ReturnType(); });
101 for (
auto& thread : m_threads)
107 template<
typename ReturnType>
108 void ThreadPool<ReturnType>::initialize()
110 for (
unsigned int i = 0; i < m_maxThreads; ++i)
112 m_threads.push_back(std::thread(&ThreadPool<ReturnType>::execute,
this));
116 template<
typename ReturnType>
119 std::future<ReturnType> future;
123 std::unique_lock<std::mutex> queueLock(m_queueMutex);
133 m_initialized =
true;
139 m_queue.emplace(task);
140 future = m_queue.back().get_future();
143 m_condition.notify_one();
149 template<
typename ReturnType>
156 std::packaged_task<ReturnType()> task;
159 std::unique_lock<std::mutex> queueLock(m_queueMutex);
162 m_condition.wait(queueLock, [
this] {
return !m_queue.empty(); });
163 task = std::move(m_queue.front());
174 smtkErrorMacro(smtk::io::Logger::instance(),
"Uncaught thread task exception.");
181 #endif // smtk_common_ThreadPool_h