46 : m_name(
std::move(name)), m_policies(
std::move(policies)) {
56 std::scoped_lock lock(m_worker_mutex);
57 for (
auto& w : m_workers) {
58 w.m_thread.request_stop();
69 template <
class Func,
class...
Args>
71 std::scoped_lock lock(m_worker_mutex);
73 auto prev = m_workers.before_begin();
74 auto cur = m_workers.begin();
76 while (cur != m_workers.end()) {
77 if (not cur->m_alive) {
82 m_name, m_policies, std::forward<Func>(func), std::forward<Args>(args)...);
89 cur = m_workers.erase_after(prev);
98 m_workers.emplace_after(prev)->Run(
99 m_name, m_policies, std::forward<Func>(func), std::forward<Args>(args)...);
107 numapp::NumaPolicies m_policies;
108 std::mutex m_worker_mutex;
109 std::forward_list<Worker> m_workers;
114 Worker(
const Worker&) =
delete;
115 Worker(Worker&&) =
delete;
116 Worker& operator=(
const Worker&) =
delete;
117 Worker& operator=(Worker&&) =
delete;
119 template <
class Func,
class...
Args>
120 void Run(std::string_view name,
121 const numapp::NumaPolicies& policies,
124 bool before = m_alive.exchange(
true);
129 m_thread = numapp::MakeJthread(
132 [alive_guard = AliveGuard{&m_alive, &AliveGuardFunction},
133 func = std::forward<Func>(func)](std::stop_token st,
auto&&... args)
mutable {
134 if constexpr (std::is_invocable_v<std::decay_t<Func>,
136 std::decay_t<Args>...>) {
137 std::invoke(func, st, std::move(args)...);
139 std::invoke(func, move(args)...);
142 std::forward<Args>(args)...);
144 std::jthread m_thread;
145 std::atomic<bool> m_alive{
false};
148 static void AliveGuardFunction(std::atomic<bool>* alive_ptr) {
149 alive_ptr->store(
false, std::memory_order_release);
151 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:70