22#include <asio/awaitable.hpp>
23#include <asio/io_context.hpp>
24#include <asio/steady_timer.hpp>
25#include <asio/use_awaitable.hpp>
29#include "utils/singleton.hpp"
45template<
typename T =
void>
48using duration = std::chrono::steady_clock::duration;
59 using shutdown_handler_type = std::function<task_type()>;
83 void spawn(task_type&& task);
100 template<
typename Fn,
typename... Args>
101 inline void post(Fn&& fn, Args&&... args) {
103 [
this, fn = std::forward<Fn>(fn),
104 args = std::make_tuple(std::decay_t<Args>(std::forward<Args>(args))...)]()
mutable {
106 std::apply(std::move(fn), std::move(args));
108 handle_unhandled_exception(
109 std::current_exception(),
"posted task");
139 bool failed() const noexcept {
return failed_; }
145 bool init(info_type _info);
148 inline std::string
desc()
const{
149 return std::format(
"async task context");
156 return context_.get_executor();
167 void handle_unhandled_exception(std::exception_ptr error,
168 std::string_view origin)
noexcept;
169 void finish_shutdown(std::exception_ptr error)
noexcept;
171 asio::io_context context_;
173 shutdown_handler_type shutdown_handler_;
174 bool failed_ {
false};
175 bool shutdown_started_ {
false};
178static_assert(utils::singleton_info<task_context::info_type>);
179static_assert(utils::singleton<task_context>);
191inline auto spawn(task_context::task_type&& task){
192 roboctrl::get<task_context>().spawn(std::forward<task_context::task_type>(task));
206template<
typename ...Args>
207inline auto post(Args&&... args)
209 roboctrl::get<task_context>().post(std::forward<Args>(args)...);
217 roboctrl::get<task_context>().run();
222 return roboctrl::get<task_context>().failed();
227 return roboctrl::get<task_context>().shutdown_requested();
232 roboctrl::get<task_context>().set_shutdown_handler(std::move(handler));
237 roboctrl::get<task_context>().request_shutdown();
249 co_await asio::post(asio::use_awaitable);
263 auto ex = roboctrl::get<task_context>().get_executor();
264 asio::steady_timer timer(ex, duration);
265 co_await timer.async_wait(asio::use_awaitable);
272 return roboctrl::get<task_context>().get_executor();
279 return roboctrl::get<task_context>().asio_context();
283 roboctrl::get<task_context>().stop();
287 using namespace async;
void request_shutdown() noexcept
请求一次安全停机。
auto asio_context() -> asio::io_context &
获取asio的io_context。
void run() noexcept
开始运行任务上下文。
bool failed() const noexcept
是否观察到过未处理的异步异常。
std::string desc() const
task_context的描述
bool shutdown_requested() const noexcept
是否已经进入一次性停机流程。
bool init(info_type _info)
初始化 task_context
auto get_executor()
获取asio的executor。
void spawn(task_type &&task)
添加一个协程任务到上下文中执行。
void set_shutdown_handler(shutdown_handler_type handler)
注册异常或外部请求共用的一次性安全停机任务。
void post(Fn &&fn, Args &&... args)
添加一个任务到上下文中执行。
用于提供日志功能的辅助基类 通过CRTP模式实现,要求派生类实现desc()方法以提供描述信息,在继承时传入派生类自身类型作为模板参数。 继承这个类后,派生类可以方便地使用log_debug、log_i...
awaitable< void > wait_for(const duration &duration)
协程任务等待。
awaitable< void > yield()
协程任务等待。用于让出当前函数的执行权。
void set_shutdown_handler(task_context::shutdown_handler_type handler)
设置全局任务上下文的一次性安全停机任务。
auto spawn(task_context::task_type &&task)
添加一个协程任务到全局任务上下文中执行。
auto post(Args &&... args)
添加一个任务到全局任务上下文中执行。
void request_shutdown()
请求运行全局任务上下文的安全停机任务。
bool failed()
查询全局任务上下文是否因未处理异常进入过安全停机。
asio::awaitable< T > awaitable
协程任务类型。
auto executor()
获取全局任务上下文的executor。
auto & io_context()
获取全局任务上下文的io_context。
bool shutdown_requested()
查询全局任务上下文是否已经进入停机流程。