PACS System 0.1.0
PACS DICOM system library
Loading...
Searching...
No Matches
executor_adapter.h
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2021-2025, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
20#pragma once
21
22#include <kcenon/common/interfaces/executor_interface.h>
23#include <kcenon/common/patterns/result.h>
24
25#include <atomic>
26#include <chrono>
27#include <condition_variable>
28#include <functional>
29#include <future>
30#include <memory>
31#include <mutex>
32#include <queue>
33#include <string>
34#include <thread>
35
36namespace kcenon::thread {
37class thread_pool;
38} // namespace kcenon::thread
39
41
42// Forward declaration
43class thread_pool_interface;
44
65class lambda_job : public kcenon::common::interfaces::IJob {
66public:
67 using job_function = std::function<kcenon::common::VoidResult()>;
68
76 explicit lambda_job(
77 job_function func,
78 std::string name = "lambda_job",
79 int priority = 0)
80 : func_(std::move(func))
81 , name_(std::move(name))
82 , priority_(priority) {}
83
91 template <typename F>
92 requires std::is_void_v<std::invoke_result_t<F>>
93 explicit lambda_job(F&& func, std::string name = "lambda_job", int priority = 0)
94 : func_([f = std::forward<F>(func)]() -> kcenon::common::VoidResult {
95 f();
96 return kcenon::common::VoidResult(std::monostate{});
97 })
98 , name_(std::move(name))
99 , priority_(priority) {}
100
101 kcenon::common::VoidResult execute() override {
102 if (!func_) {
103 return kcenon::common::VoidResult(
104 kcenon::common::error_info{-1, "No function provided", "executor"});
105 }
106 return func_();
107 }
108
109 [[nodiscard]] std::string get_name() const override { return name_; }
110 [[nodiscard]] int get_priority() const override { return priority_; }
111
112private:
114 std::string name_;
116};
117
144class thread_pool_executor_adapter : public kcenon::common::interfaces::IExecutor {
145public:
152 std::shared_ptr<kcenon::thread::thread_pool> pool);
153
161 explicit thread_pool_executor_adapter(std::size_t worker_count);
162
167
168 // Non-copyable, non-movable
173
174 // =========================================================================
175 // IExecutor Implementation
176 // =========================================================================
177
186 [[nodiscard]] kcenon::common::Result<std::future<void>> execute(
187 std::unique_ptr<kcenon::common::interfaces::IJob>&& job) override;
188
196 [[nodiscard]] kcenon::common::Result<std::future<void>> execute_delayed(
197 std::unique_ptr<kcenon::common::interfaces::IJob>&& job,
198 std::chrono::milliseconds delay) override;
199
203 [[nodiscard]] std::size_t worker_count() const override;
204
208 [[nodiscard]] bool is_running() const override;
209
213 [[nodiscard]] std::size_t pending_tasks() const override;
214
220 void shutdown(bool wait_for_completion = true) override;
221
222 // =========================================================================
223 // Convenience Methods
224 // =========================================================================
225
236 template <typename F>
237 requires std::invocable<F>
238 [[nodiscard]] auto submit(F&& func, std::string name = "submitted_job")
240 auto job = std::make_unique<lambda_job>(std::forward<F>(func), std::move(name));
241 return execute(std::move(job));
242 }
243
247 [[nodiscard]] auto get_underlying_pool() const
248 -> std::shared_ptr<kcenon::thread::thread_pool>;
249
250private:
251 std::shared_ptr<kcenon::thread::thread_pool> pool_;
252 std::atomic<bool> running_{true};
253 std::atomic<std::size_t> pending_count_{0};
254
255 // For delayed execution
256 std::thread delay_thread_;
257 std::mutex delay_mutex_;
258 std::condition_variable delay_cv_;
259 std::atomic<bool> shutdown_requested_{false};
260
262 std::chrono::steady_clock::time_point execute_at;
263 std::function<void()> task;
264
265 bool operator>(const delayed_task& other) const {
266 return execute_at > other.execute_at;
267 }
268 };
269 std::priority_queue<delayed_task, std::vector<delayed_task>,
270 std::greater<delayed_task>> delayed_tasks_;
271};
272
282[[nodiscard]] std::shared_ptr<kcenon::common::interfaces::IExecutor>
283make_executor(std::shared_ptr<thread_pool_interface> pool_interface);
284
285} // namespace kcenon::pacs::integration
IJob implementation that wraps a callable.
lambda_job(job_function func, std::string name="lambda_job", int priority=0)
Construct a lambda job.
std::function< kcenon::common::VoidResult()> job_function
kcenon::common::VoidResult execute() override
lambda_job(F &&func, std::string name="lambda_job", int priority=0)
Construct from void-returning callable.
std::string get_name() const override
IExecutor implementation using kcenon::thread::thread_pool.
thread_pool_executor_adapter(const thread_pool_executor_adapter &)=delete
thread_pool_executor_adapter & operator=(thread_pool_executor_adapter &&)=delete
thread_pool_executor_adapter & operator=(const thread_pool_executor_adapter &)=delete
thread_pool_executor_adapter(thread_pool_executor_adapter &&)=delete
std::priority_queue< delayed_task, std::vector< delayed_task >, std::greater< delayed_task > > delayed_tasks_
auto submit(F &&func, std::string name="submitted_job") -> kcenon::common::Result< std::future< void > >
Submit a void-returning callable directly.
std::shared_ptr< kcenon::common::interfaces::IExecutor > make_executor(std::shared_ptr< thread_pool_interface > pool_interface)
Create an IExecutor from a thread_pool_interface.
std::string_view name