45 : m_name(
std::move(name)), m_policies(
std::move(policies)) {
55 std::scoped_lock lock(m_worker_mutex);
56 for (
auto& w : m_workers) {
57 w.m_thread.request_stop();
68 template <
class Func,
class...
Args>
70 std::scoped_lock lock(m_worker_mutex);
72 auto prev = m_workers.before_begin();
73 auto cur = m_workers.begin();
75 while (cur != m_workers.end()) {
76 if (not cur->m_alive) {
81 m_name, m_policies, std::forward<Func>(func), std::forward<Args>(args)...);
88 cur = m_workers.erase_after(prev);
97 m_workers.emplace_after(prev)->Run(
98 m_name, m_policies, std::forward<Func>(func), std::forward<Args>(args)...);
106 numapp::NumaPolicies m_policies;
107 std::mutex m_worker_mutex;
108 std::forward_list<Worker> m_workers;
113 Worker(
const Worker&) =
delete;
114 Worker(Worker&&) =
delete;
115 Worker& operator=(
const Worker&) =
delete;
116 Worker& operator=(Worker&&) =
delete;
118 template <
class Func,
class...
Args>
119 void Run(std::string_view name,
120 const numapp::NumaPolicies& policies,
123 bool before = m_alive.exchange(
true);
128 m_thread = numapp::MakeJthread(
131 [alive_guard = AliveGuard{&m_alive, &AliveGuardFunction},
132 func = std::forward<Func>(func)](std::stop_token st,
auto&&... args)
mutable {
133 if constexpr (std::is_invocable_v<std::decay_t<Func>,
135 std::decay_t<Args>...>) {
136 std::invoke(func, st, std::move(args)...);
138 std::invoke(func, move(args)...);
141 std::forward<Args>(args)...);
143 std::jthread m_thread;
144 std::atomic<bool> m_alive{
false};
147 static void AliveGuardFunction(std::atomic<bool>* alive_ptr) {
148 alive_ptr->store(
false, std::memory_order_release);
150 using AliveGuard = std::unique_ptr<std::atomic<bool>,
decltype(&AliveGuardFunction)>;
void Submit(Func &&func, Args &&... args)
Execute a function in a new thread which gets joined when it finishes or when the pool is destroyed.
Definition dynamicThreadPool.hpp:69