21 using Task = std::packaged_task<void()>;
27 throw std::invalid_argument(
"The argument 'threadCount' has to be greate or equal to one!");
28 m_threads.reserve(threadCount);
29 for(std::size_t i = 0; i < threadCount; ++i)
30 m_threads.emplace_back([
this] { threadFunc(); });
37 for(
auto& t : m_threads)
39 if(std::this_thread::get_id() == t.get_id())
41 std::cerr <<
"ERROR in ThreadPool joins itself" << std::endl;
55 template<
typename TFnObj,
typename... TArgs>
56 auto enqueueTask(TFnObj&& task, TArgs&&... args) -> std::future<void>
62 # define ALPAKA_NOEXCEPT(...)
64 # define ALPAKA_NOEXCEPT(...) noexcept(__VA_ARGS__)
67 =
Task{[=, t = std::forward<TFnObj>(task)]()
ALPAKA_NOEXCEPT(noexcept(task(args...))) { t(args...); }};
68 #undef ALPAKA_NOEXCEPT
70 auto future = ptask.get_future();
72 std::lock_guard<std::mutex> lock{m_mutex};
73 m_tasks.push(std::move(ptask));
81 while(!m_stop.load(std::memory_order_relaxed))
83 std::optional<Task> task;
85 std::lock_guard<std::mutex> lock{m_mutex};
88 task = std::move(m_tasks.front());
95 std::this_thread::yield();
99 std::vector<std::thread> m_threads;
100 std::queue<Task> m_tasks;
102 std::atomic<bool> m_stop =
false;
#define ALPAKA_NOEXCEPT(...)
Defines implementation details that should not be used directly by the user.
A thread pool yielding when there is not enough work to be done.
std::packaged_task< void()> Task
ThreadPool(std::size_t threadCount)
Creates a thread pool with a given thread count.
~ThreadPool()
Destroys the thread pool, blocking until all enqueued work is done.
auto enqueueTask(TFnObj &&task, TArgs &&... args) -> std::future< void >
Runs the given function on one of the pool in First In First Out (FIFO) order.