@@ -5,7 +5,7 @@ import CppUtils.Chrono.Concept;
55import CppUtils.Thread.UniqueLocker;
66import CppUtils.Thread.SharedLocker;
77import CppUtils.Thread.ThreadLoop;
8- import CppUtils.Execution.ScopeGuard ;
8+ import CppUtils.Thread.ThreadPool ;
99
1010export namespace CppUtils::Thread
1111{
@@ -47,20 +47,32 @@ export namespace CppUtils::Thread
4747 public:
4848 inline Scheduler(
4949 Clock::duration step = Clock::duration::zero(),
50- std::function<void(std::exception_ptr)> onError = nullptr):
50+ std::size_t numberThreads = std::thread::hardware_concurrency(),
51+ std::function<void(std::exception_ptr)> onError = nullptr,
52+ std::function<void()> finally = nullptr):
5153 m_step{step},
52- m_loop{
54+ m_finally{std::move(finally)},
55+ m_threadLoop{
5356 [this] { runLoop(); },
5457 [this] { m_condition.notify_all(); },
55- std::move(onError)}
58+ onError},
59+ m_threadPool{
60+ numberThreads,
61+ onError,
62+ [this] {
63+ if (m_finally)
64+ m_finally();
65+ if (--m_processingTasks == 0)
66+ m_condition.notify_all();
67+ }}
5668 {
57- m_loop .start();
69+ m_threadLoop .start();
5870 }
5971
6072 inline ~Scheduler() noexcept
6173 {
6274 cancelAll();
63- m_loop .requestStop();
75+ m_threadLoop .requestStop();
6476 }
6577
6678 inline auto schedule(Task task, TimePoint when) -> std::size_t
@@ -120,9 +132,9 @@ export namespace CppUtils::Thread
120132 if (std::empty(set))
121133 {
122134 m_condition.wait(accessor.getLockGuard(), [this, &accessor] {
123- return not std::empty(accessor.value().set) or m_loop .isStopRequested();
135+ return not std::empty(accessor.value().set) or m_threadLoop .isStopRequested();
124136 });
125- if (m_loop .isStopRequested())
137+ if (m_threadLoop .isStopRequested())
126138 return;
127139 if (std::empty(set))
128140 {
@@ -136,7 +148,7 @@ export namespace CppUtils::Thread
136148 if (first->time > Clock::now())
137149 {
138150 m_condition.wait_until(accessor.getLockGuard(), first->time, [&, first] {
139- return m_loop .isStopRequested() or first->cancelled or std::empty(set) or (*std::begin(set) != first) or first->time <= Clock::now();
151+ return m_threadLoop .isStopRequested() or first->cancelled or std::empty(set) or (*std::begin(set) != first) or first->time <= Clock::now();
140152 });
141153 return;
142154 }
@@ -161,14 +173,10 @@ export namespace CppUtils::Thread
161173 return;
162174
163175 m_processingTasks += std::size(tasksToRun);
164- for (const auto& task : tasksToRun)
165- {
166- auto _ = Execution::ScopeGuard{[this] {
167- if (--m_processingTasks == 0)
168- m_condition.notify_all();
169- }};
170- std::invoke(task);
171- }
176+ for (auto&& task : tasksToRun)
177+ m_threadPool.call([task = std::move(task)] {
178+ std::invoke(task);
179+ });
172180 }
173181
174182 private:
@@ -177,7 +185,10 @@ export namespace CppUtils::Thread
177185 UniqueLocker<Items> m_items;
178186 std::atomic_size_t m_processingTasks = 0;
179187
188+ std::function<void()> m_finally;
189+
180190 std::condition_variable m_condition;
181- ThreadLoop m_loop;
191+ ThreadLoop m_threadLoop;
192+ ThreadPool m_threadPool;
182193 };
183194}
0 commit comments