32template <
typename PoolType>
36 explicit PoolWithErrors(
size_t num_threads = std::thread::hardware_concurrency())
37 : pool_(num_threads), error_handler_(std::make_shared<
ErrorHandler>())
52 template <
typename Arg1,
typename Arg2,
typename... Args>
54 : pool_(std::forward<Arg1>(arg1), std::forward<Arg2>(arg2), std::forward<Args>(args)...),
62 template <
typename F,
typename... Args>
65 return submit_impl({}, std::forward<F>(f), std::forward<Args>(args)...);
71 template <
typename F,
typename... Args>
75 return submit_impl(description, std::forward<F>(f), std::forward<Args>(args)...);
81 template <
typename F,
typename... Args>
85 return try_submit_impl({}, std::forward<F>(f), std::forward<Args>(args)...);
90 return error_handler_->add_callback(std::move(callback));
93 template <
typename Callback,
94 std::enable_if_t<!std::is_same_v<detail::remove_cvref_t<Callback>,
ErrorCallback>,
int> = 0>
97 return error_handler_->add_callback(std::forward<Callback>(callback));
102 return error_handler_->remove_callback(
id);
107 error_handler_->clear_callbacks();
112 return error_handler_->error_count();
117 error_handler_->reset_error_count();
120 [[nodiscard]]
auto pool() -> PoolType&
127 return pool_.get_statistics();
133 return pool_.configure_threads(name_prefix, policy, priority);
138 return pool_.set_affinity(affinity);
143 return pool_.distribute_across_cpus();
148 pool_.wait_for_tasks();
156 [[nodiscard]]
auto size() const noexcept ->
size_t
163 return pool_.pending_tasks();
167 template <
typename F,
typename... Args>
168 auto submit_impl(std::string description, F&& f, Args&&... args)
171 using return_type = std::invoke_result_t<F, Args...>;
172 auto handler = error_handler_;
174 [bound =
detail::bind_args(std::forward<F>(f), std::forward<Args>(args)...), handler,
175 desc = std::move(description)]()
mutable -> return_type {
178 if constexpr (std::is_void_v<return_type>)
194 auto future = pool_.submit(std::move(wrapped_task));
195 return FutureWithErrorHandler<std::invoke_result_t<F, Args...>>(std::move(future));
198 template <
typename F,
typename... Args>
199 auto try_submit_impl(std::string description, F&& f, Args&&... args)
200 -> expected<FutureWithErrorHandler<std::invoke_result_t<F, Args...>>, std::error_code>
202 using return_type = std::invoke_result_t<F, Args...>;
203 auto handler = error_handler_;
205 [bound =
detail::bind_args(std::forward<F>(f), std::forward<Args>(args)...), handler,
206 desc = std::move(description)]()
mutable -> return_type {
209 if constexpr (std::is_void_v<return_type>)
225 auto result = pool_.try_submit(std::move(wrapped_task));
226 if (!result.has_value())
227 return unexpected(result.error());
228 return FutureWithErrorHandler<std::invoke_result_t<F, Args...>>(std::move(result.value()));
232 std::shared_ptr<ErrorHandler> error_handler_;
Central registry and dispatcher for task-error callbacks.
A move-only future wrapper that supports an error callback.
Thread pool wrapper that combines any pool type with an ErrorHandler.
auto try_submit(F &&f, Args &&... args) -> expected< FutureWithErrorHandler< std::invoke_result_t< F, Args... > >, std::error_code >
Submit a task, returning an error instead of throwing on shutdown.
auto submit_with_description(std::string const &description, F &&f, Args &&... args) -> FutureWithErrorHandler< std::invoke_result_t< F, Args... > >
Submit a task with a description for better error messages.
auto distribute_across_cpus() -> decltype(auto)
PoolWithErrors(Arg1 &&arg1, Arg2 &&arg2, Args &&... args)
Construct with forwarded pool arguments.
auto add_error_callback(Callback &&callback) -> size_t
auto add_error_callback(ErrorCallback callback) -> size_t
auto get_statistics() const -> decltype(auto)
auto pending_tasks() const -> size_t
auto error_count() const -> size_t
auto set_affinity(ThreadAffinity const &affinity) -> decltype(auto)
PoolWithErrors(size_t num_threads=std::thread::hardware_concurrency())
auto remove_error_callback(size_t id) -> bool
auto configure_threads(std::string const &name_prefix, SchedulingPolicy policy=SchedulingPolicy::OTHER, ThreadPriority priority=ThreadPriority::normal()) -> decltype(auto)
auto submit(F &&f, Args &&... args) -> FutureWithErrorHandler< std::invoke_result_t< F, Args... > >
Submit a task with automatic error handling.
auto pool() -> PoolType &
auto size() const noexcept -> size_t
void clear_error_callbacks()
Manages a set of CPU indices to which a thread may be bound.
Value-semantic wrapper for a thread scheduling priority.
static constexpr auto normal() noexcept -> ThreadPriority
A result type that holds either a value of type T or an error of type E.
Error handling primitives: TaskError, ErrorHandler, and ErrorHandledTask.
auto bind_args(F &&f, Args &&... args)
Bind a callable with its arguments into a nullary lambda.
SchedulingPolicy
Enumeration of available thread scheduling policies.
@ OTHER
Standard round-robin time-sharing.
PoolWithErrors< FastThreadPool > FastThreadPoolWithErrors
FastThreadPool with integrated error handling.
detail::copyable_callable< void(TaskError const &)> ErrorCallback
Signature for error-handling callbacks registered with ErrorHandler.
PoolWithErrors< ThreadPool > ThreadPoolWithErrors
ThreadPool with integrated error handling.
PoolWithErrors< HighPerformancePool > HighPerformancePoolWithErrors
HighPerformancePool with integrated error handling.
static auto capture(std::string description={}) -> TaskError
Capture the current in-flight exception into a TaskError.
Thread pools: HighPerformancePool, ThreadPoolBase, LightweightPoolT, and GlobalPool.