RTC Toolkit 6.0.0
Loading...
Searching...
No Matches
dynamicThreadPool.hpp
Go to the documentation of this file.
1
11
12#ifndef RTCTK_COMPONENTFRAMEWORK_DYNAMICTHREADPOOL_HPP
13#define RTCTK_COMPONENTFRAMEWORK_DYNAMICTHREADPOOL_HPP
14
15#include <atomic>
16#include <cassert>
17#include <forward_list>
18#include <memory>
19#include <mutex>
20#include <stop_token>
21#include <thread>
22
23#include <functional>
24#include <numapp/numapolicies.hpp>
25#include <numapp/thread.hpp>
26#include <utility>
27
29
37public:
44 explicit DynamicThreadPool(std::string name, numapp::NumaPolicies policies = {})
45 : m_name(std::move(name)), m_policies(std::move(policies)) {
46 }
47
48 // neither copyable nor movable
53
55 std::scoped_lock lock(m_worker_mutex);
56 for (auto& w : m_workers) {
57 w.m_thread.request_stop();
58 }
59 m_workers.clear(); // jthreads auto-join
60 }
61
68 template <class Func, class... Args>
69 void Submit(Func&& func, Args&&... args) {
70 std::scoped_lock lock(m_worker_mutex);
71 bool stored = false;
72 auto prev = m_workers.before_begin();
73 auto cur = m_workers.begin();
74
75 while (cur != m_workers.end()) {
76 if (not cur->m_alive) {
77 if (not stored) {
78 // false linter error
79 // NOLINTBEGIN(bugprone-use-after-move)
80 cur->Run(
81 m_name, m_policies, std::forward<Func>(func), std::forward<Args>(args)...);
82 // NOLINTEND(bugprone-use-after-move)
83 stored = true;
84 prev = cur;
85 ++cur;
86 } else {
87 // we already have a place, remove old thread
88 cur = m_workers.erase_after(prev);
89 }
90 } else {
91 prev = cur;
92 ++cur;
93 }
94 }
95 // no spot free
96 if (not stored) {
97 m_workers.emplace_after(prev)->Run(
98 m_name, m_policies, std::forward<Func>(func), std::forward<Args>(args)...);
99 }
100 }
101
102private:
103 class Worker;
104
105 std::string m_name;
106 numapp::NumaPolicies m_policies;
107 std::mutex m_worker_mutex;
108 std::forward_list<Worker> m_workers;
109
110 class Worker {
111 public:
112 // no copy because of thread, no move because of atomic
113 Worker(const Worker&) = delete;
114 Worker(Worker&&) = delete;
115 Worker& operator=(const Worker&) = delete;
116 Worker& operator=(Worker&&) = delete;
117 Worker() = default;
118 template <class Func, class... Args>
119 void Run(std::string_view name,
120 const numapp::NumaPolicies& policies,
121 Func&& func,
122 Args&&... args) {
123 bool before = m_alive.exchange(true);
124 // The following line is needed to avoid compiler warnings in release builds,
125 // where assert becomes a no-op.
126 (void)before;
127 assert(not before);
128 m_thread = numapp::MakeJthread(
129 name,
130 policies,
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>,
134 std::stop_token,
135 std::decay_t<Args>...>) {
136 std::invoke(func, st, std::move(args)...);
137 } else {
138 std::invoke(func, move(args)...);
139 }
140 },
141 std::forward<Args>(args)...);
142 }
143 std::jthread m_thread;
144 std::atomic<bool> m_alive{false};
145
146 private:
147 static void AliveGuardFunction(std::atomic<bool>* alive_ptr) {
148 alive_ptr->store(false, std::memory_order_release);
149 }
150 using AliveGuard = std::unique_ptr<std::atomic<bool>, decltype(&AliveGuardFunction)>;
151 };
152};
153} // namespace rtctk::componentFramework
154
155#endif // RTCTK_COMPONENTFRAMEWORK_DYNAMICTHREADPOOL_HPP
Class used to parse default command line arguments.
Definition rtcComponentArgs.hpp:32
DynamicThreadPool(const DynamicThreadPool &)=delete
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
DynamicThreadPool & operator=(const DynamicThreadPool &)=delete
DynamicThreadPool & operator=(DynamicThreadPool &&)=delete
DynamicThreadPool(std::string name, numapp::NumaPolicies policies={})
Create a new DynamicThreadPool.
Definition dynamicThreadPool.hpp:44
DynamicThreadPool(DynamicThreadPool &&)=delete
~DynamicThreadPool()
Definition dynamicThreadPool.hpp:54
Definition commandReplier.cpp:21
Definition ddsSub.hpp:155