24#include "flow/error/error.hpp"
33template<
typename Scheduled_task_handler>
37 Scheduled_task_handler&& task_body_moved)
39 using boost::chrono::round;
40 using boost::chrono::milliseconds;
42 using boost::asio::bind_executor;
43 using boost::asio::get_associated_executor;
44 using boost::asio::post;
119 auto task = boost::make_shared<Scheduled_task_handle_state>
120 (task_id, single_threaded, task_engine, [task_id, get_logger, get_log_component,
122 task_body = std::move(task_body_moved)]
123 (
bool short_fire)
mutable
126 const auto executor = get_associated_executor(task_body);
128 bind_executor(executor, [get_logger, get_log_component, task_id,
129 task_body = std::move(task_body), short_fire]()
131 FLOW_LOG_TRACE(
"Scheduled task [" << task_id <<
"]: Body starting; short-fired? = [" << short_fire <<
"].");
132 task_body(short_fire);
133 FLOW_LOG_TRACE(
"Scheduled task [" << task_id <<
"]: Body finished without throwing exception.");
140 auto& timer = task->m_timer;
143 "to fire in [" << round<milliseconds>(from_now) <<
"]; "
144 "task engine [" <<
static_cast<void*
>(task_engine) <<
"]; "
145 "single-threaded optimizations applicable? = [" << single_threaded <<
"].");
147 timer.expires_after(from_now);
155 timer.async_wait([get_logger, get_log_component, task](
const Error_code& sys_err_code)
157 const bool single_threaded = !task->m_mutex_unless_single_threaded;
171 if (sys_err_code == boost::asio::error::operation_aborted)
175 assert(task->m_fired != task->m_canceled);
180 assert(task->m_fired != task->m_canceled);
185 if (sys_err_code && (sys_err_code != boost::asio::error::operation_aborted))
188 FLOW_LOG_WARNING(
"Timer system error; just logged; totally unexpected; pretending it fired normally.");
196 auto should_fire = [&]() ->
bool
200 FLOW_LOG_TRACE(
"Scheduled task [" << task->m_id <<
"] native timer fired (could be due to cancel() call), "
201 "but user handler already began executing earlier. Done.");
205 if (task->m_canceled)
207 FLOW_LOG_TRACE(
"Scheduled task [" << task->m_id <<
"] native timer fired (could be due to cancel() call), "
208 "but task was already canceled earlier. Done.");
213 FLOW_LOG_TRACE(
"Scheduled task [" << task->m_id <<
"] native timer fired (could be due to cancel() call), "
214 "and nothing has fired or canceled task already. Proceeding with task (through post()).");
216 task->m_fired =
true;
223 noop = !should_fire();
228 noop = !should_fire();
237 (task->m_body)(
false);
238 FLOW_LOG_TRACE(
"Scheduled task [" << task->m_id <<
"]: Body-post()ing function finished.");
244template<
typename Scheduled_task_handler>
248 Scheduled_task_handler&& task_body_moved)
257 return schedule_task_from_now<Scheduled_task_handler>(logger_ptr,
258 at - Fine_clock::now(),
259 single_threaded, task_engine, std::move(task_body_moved));
Interface that the user should implement, passing the implementing Logger into logging classes (Flow'...
static id_t create_unique_id()
Short-hand for Unique_id_holder().unique_id(); useful when all you want is the unique integer itself.
#define FLOW_ERROR_SYS_ERROR_LOG_WARNING()
Logs a warning about the (often errno-based or from a library) error code in sys_err_code.
#define FLOW_LOG_WARNING(ARG_stream_fragment)
Logs a WARNING message into flow::log::Logger *get_logger() with flow::log::Component get_log_compone...
#define FLOW_LOG_SET_CONTEXT(ARG_logger_ptr, ARG_component_payload)
For the rest of the block within which this macro is instantiated, causes all FLOW_LOG_....
#define FLOW_LOG_TRACE(ARG_stream_fragment)
Logs a TRACE message into flow::log::Logger *get_logger() with flow::log::Component get_log_component...
Flow module containing miscellaneous general-use facilities that don't fit into any other Flow module...
boost::unique_lock< Mutex > Lock_guard
Short-hand for advanced-capability RAII lock guard for any mutex, ensuring exclusive ownership of tha...
Scheduled_task_handle schedule_task_from_now(log::Logger *logger_ptr, const Fine_duration &from_now, bool single_threaded, Task_engine *task_engine, Scheduled_task_handler &&task_body_moved)
Schedule the given function to execute in a certain amount of time: A handy wrapper around Timer (asi...
boost::shared_ptr< Scheduled_task_handle_state > Scheduled_task_handle
Black-box type that represents a handle to a scheduled task as scheduled by schedule_task_at() or sch...
Scheduled_task_handle schedule_task_at(log::Logger *logger_ptr, const Fine_time_pt &at, bool single_threaded, Task_engine *task_engine, Scheduled_task_handler &&task_body_moved)
Identical to schedule_task_from_now() except the time is specified in absolute terms.
boost::asio::io_service Task_engine
Short-hand for boost.asio event service, the central class of boost.asio.
boost::system::error_code Error_code
Short-hand for a boost.system error code (which basically encapsulates an integer/enum error code and...
Fine_clock::duration Fine_duration
A high-res time duration as computed from two Fine_time_pts.
Fine_clock::time_point Fine_time_pt
A high-res time point as returned by Fine_clock::now() and suitable for precise time math in general.