22#include <flow/error/error.hpp>
23#include <boost/move/make_unique.hpp>
24#include <boost/asio/connect_pipe.hpp>
37 m_nickname(nickname_str),
38 m_worker_started(false),
39 m_worker(get_logger(),
42 std::string(
"TEvE-") + m_nickname)
44 FLOW_LOG_TRACE(
"Timer_event_emitter [" << *
this <<
"]: Created; worker thread not yet started (lazily started "
45 "by first timer async-wait, if any).");
58 using flow::util::Timer;
60 return Timer{*(
m_worker.task_engine())};
65 using boost::asio::writable_pipe;
66 using boost::asio::connect_pipe;
67 using boost::movelib::make_unique;
69 auto& task_engine = *(
m_worker.task_engine());
70 auto read_end = make_unique<Timer_fired_read_end>(task_engine);
71 auto write_end = make_unique<writable_pipe>(task_engine);
73 connect_pipe(*read_end, *write_end, sys_err_code);
78 FLOW_LOG_FATAL(
"connect_pipe() failed; this should never happen. Details follow.");
79 FLOW_ERROR_SYS_ERROR_LOG_FATAL();
80 assert(
false &&
"connect_pipe() failed; this should never happen."); std::abort();
91 assert(result.second);
93 FLOW_LOG_TRACE(
"Timer_event_emitter [" << *
this <<
"]: Pipe created; read-end ptr = [" << read_end_ref.get() <<
"].");
95 return read_end_ref.get();
100 FLOW_LOG_TRACE(
"Timer_event_emitter [" << *
this <<
"]: Starting timer async-wait; when/if it fires, "
101 "we will write to write-end corresponding to read-end ptr = [" << read_end <<
"].");
107 FLOW_LOG_TRACE(
"Timer_event_emitter [" << *
this <<
"]: First async-wait => lazily starting thread.");
109 m_worker.start(flow::async::reset_this_thread_pinning);
119 assert((it !=
m_signal_pipe_writers.end()) &&
"timer_async_wait() invoked on read_end from another *this?");
120 const auto write_end = it->second.get();
122 timer->async_wait([
this, write_end, read_end](
const Error_code& async_err_code)
126 auto sys_err_code = async_err_code;
128 if (sys_err_code == boost::asio::error::operation_aborted)
139 FLOW_ERROR_SYS_ERROR_LOG_WARNING();
140 FLOW_LOG_WARNING(
"Timer_event_emitter [" << *
this <<
"]: "
141 "Timer system error; just logged; totally unexpected; pretending it fired normally.");
144 FLOW_LOG_TRACE(
"Timer_event_emitter [" << *
this <<
"]: Timer fired. Pushing byte to pipe; "
145 "read_end ptr = [" << read_end <<
"]. User code should detect event soon and cause byte "
154 FLOW_LOG_TRACE(
"Timer_event_emitter [" << *
this <<
"]: Timer presumably fired and pushed byte to pipe; "
163 os <<
'[' << val.
m_nickname <<
"]@" <<
static_cast<const void*
>(&val);
An object of this type, used internally to implement sync_io-pattern objects that require timer event...
bool m_worker_started
Whether m_worker.start() has already been lazily called (first timer_async_wait()); initially false.
boost::asio::readable_pipe Timer_fired_read_end
Object representing the read end of IPC mechanism, where readable status indicates the associated tim...
boost::unordered_flat_map< Timer_fired_read_end *, boost::movelib::unique_ptr< boost::asio::writable_pipe > > m_signal_pipe_writers
Stores the write-ends of the pipes created in create_timer_signal_pipe(), indexed by pointer to their...
const std::string m_nickname
Nickname as passed to ctor.
void consume_timer_firing_signal(Timer_fired_read_end *read_end)
Must be called after a timer_async_wait()-triggered timer fired, before invoking that method for the ...
void timer_async_wait(flow::util::Timer *timer, Timer_fired_read_end *read_end)
To be used on a timer T returned by create_timer(), this is the replacement for the usual T....
~Timer_event_emitter()
Ends background thread, if any started; hence no timer-firings will execute after.
Timer_event_emitter(flow::log::Logger *logger_ptr, String_view nickname_str)
Constructs emitter.
flow::util::Timer create_timer()
Creates idle timer for use with timer_async_wait() subsequently.
flow::async::Single_thread_task_loop m_worker
The thread where (only) timer-firing events (from create_timer()-created Timers) execute.
Timer_fired_read_end * create_timer_signal_pipe()
Creates, and internally stores, an IPC mechanism instance intended for use with a given create_timer(...
std::vector< boost::movelib::unique_ptr< Timer_fired_read_end > > m_signal_pipe_readers
The readers (never null) returned by create_timer_signal_pipe().
Contains common code, as well as important explanatory documentation in the following text,...
std::ostream & operator<<(std::ostream &os, const Timer_event_emitter &val)
Prints string representation of the given Timer_event_emitter to the given ostream.
void pipe_produce(flow::log::Logger *logger_ptr, Pipe_writer *pipe)
Writes a byte to the given pipe writer.
void pipe_consume(flow::log::Logger *logger_ptr, Pipe_reader *pipe)
Reads a byte via the given pipe reader.
flow::util::String_view String_view
Short-hand for Flow's String_view.
Log_component
The flow::log::Component payload enumeration containing various log components used by Flow-IPC inter...
flow::Error_code Error_code
Short-hand for flow::Error_code which is very common.