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