7#include "function_timer.hpp"
8#include "socket_event.hpp"
9#include "../container/module.hpp"
10#include "../utility/utility.hpp"
11#include "../macros.hpp"
18hi_export_module(hikogui.dispatch.loop : intf);
32 impl_type() : _thread_id(current_thread_id()) {}
40 virtual void set_maximum_frame_rate(
double frame_rate)
noexcept = 0;
41 virtual void set_vsync_monitor_id(uintptr_t
id)
noexcept = 0;
43 void wfree_post_function(
auto&& func)
noexcept
45 return _function_fifo.add_function(hi_forward(func));
48 void post_function(
auto&& func)
noexcept
50 _function_fifo.add_function(hi_forward(func));
54 [[nodiscard]]
auto async_function(
auto&& func)
noexcept
56 auto future = _function_fifo.add_async_function(hi_forward(func));
63 auto [token, first_to_call] = _function_timer.delay_function(time_point, hi_forward(func));
73 auto [token, first_to_call] = _function_timer.repeat_function(period, time_point, hi_forward(func));
83 auto [token, first_to_call] = _function_timer.repeat_function(period, hi_forward(func));
93 virtual void remove_socket(
int fd) = 0;
94 virtual int resume(std::stop_token stop_token)
noexcept = 0;
95 virtual void resume_once(
bool block)
noexcept = 0;
97 [[nodiscard]]
bool on_thread()
const noexcept
99 return current_thread_id() == _thread_id;
105 virtual void notify_has_send()
noexcept = 0;
110 std::optional<int> _exit_code = {};
111 double _maximum_frame_rate = 30.0;
113 thread_id _thread_id;
123 loop& operator=(
loop const&) = delete;
124 loop& operator=(
loop&&) noexcept = default;
128 [[nodiscard]] hi_no_inline static
loop& local() noexcept
131 _local = std::make_unique<loop>();
141 [[nodiscard]] hi_no_inline
static loop&
main() noexcept
143 if (
auto ptr = _main.load(std::memory_order::acquire)) {
147 hi_axiom(_timer.load(std::memory_order::relaxed) ==
nullptr,
"loop::main() must be called before loop::timer()");
151 set_thread_name(
"main");
154 ptr->_pimpl->is_main =
true;
155 _main.store(ptr, std::memory_order::release);
163 [[nodiscard]] hi_no_inline
static loop&
timer() noexcept
167 [[maybe_unused]] hilet &tmp = loop::main();
169 return *start_subsystem_or_terminate(_timer,
nullptr, timer_init, timer_deinit);
180 hi_assert_not_null(_pimpl);
181 return _pimpl->set_maximum_frame_rate(frame_rate);
188 hi_assert_not_null(_pimpl);
189 return _pimpl->set_vsync_monitor_id(
id);
203 hi_assert_not_null(_pimpl);
204 return _pimpl->wfree_post_function(hi_forward(func));
214 hi_assert_not_null(_pimpl);
215 return _pimpl->post_function(hi_forward(func));
227 hi_assert_not_null(_pimpl);
228 return _pimpl->async_function(hi_forward(func));
238 hi_assert_not_null(_pimpl);
239 return _pimpl->delay_function(time_point, hi_forward(func));
248 [[nodiscard]] timer_callback_token
251 hi_assert_not_null(_pimpl);
252 return _pimpl->repeat_function(period, time_point, hi_forward(func));
262 hi_assert_not_null(_pimpl);
263 return _pimpl->repeat_function(period, hi_forward(func));
272 hi_assert_not_null(_pimpl);
273 return _pimpl->subscribe_render(
std::move(f));
280 template<std::invocable<utc_nanoseconds> F>
283 hi_assert_not_null(_pimpl);
284 auto ptr = std::make_shared<render_callback_type>(std::forward<F>(f));
285 _pimpl->subscribe_render(ptr);
303 hi_assert_not_null(_pimpl);
304 return _pimpl->add_socket(fd, event_mask,
std::move(f));
313 hi_assert_not_null(_pimpl);
314 return _pimpl->remove_socket(fd);
324 int resume(std::stop_token stop_token = {})
noexcept
326 hi_assert_not_null(_pimpl);
327 return _pimpl->resume(stop_token);
345 hi_assert_not_null(_pimpl);
346 return _pimpl->resume_once(block);
355 hi_assert_not_null(_pimpl);
356 return _pimpl->on_thread();
360 static loop *timer_init() noexcept
362 hi_assert(not _timer_thread.joinable());
364 _timer_thread = std::jthread{[](std::stop_token stop_token) {
365 _timer.store(
std::addressof(loop::local()), std::memory_order::release);
367 set_thread_name(
"timer");
368 loop::local().resume(stop_token);
372 if (
auto ptr = _timer.load(std::memory_order::relaxed)) {
379 static void timer_deinit() noexcept
381 if (
auto const *
const ptr = _timer.exchange(
nullptr, std::memory_order::acquire)) {
382 hi_assert(_timer_thread.joinable());
383 _timer_thread.request_stop();
384 _timer_thread.join();
398 inline static std::jthread _timer_thread;
405void notifier<
Result(
Args...)>::loop_local_post_function(F&& f)
const noexcept
407 return loop::local().post_function(std::forward<F>(f));
412void notifier<
Result(
Args...)>::loop_main_post_function(F&& f)
const noexcept
414 return loop::main().post_function(std::forward<F>(f));
419void notifier<
Result(
Args...)>::loop_timer_post_function(F&& f)
const noexcept
421 return loop::timer().post_function(std::forward<F>(f));
DOXYGEN BUG.
Definition algorithm.hpp:16
@ local
Call the function asynchronously from the current thread's loop.
constexpr Out narrow_cast(In const &rhs) noexcept
Cast numeric values without loss of precision.
Definition cast.hpp:377
A fifo (First-in, Firts-out) for asynchronous calls.
Definition function_fifo.hpp:24
A time that calls functions.
Definition function_timer.hpp:25
Definition loop_intf.hpp:22
void resume_once(bool block=false) noexcept
Resume for a single iteration.
Definition loop_intf.hpp:343
bool on_thread() const noexcept
Check if the current thread is the same as the loop's thread.
Definition loop_intf.hpp:353
static hi_no_inline loop & timer() noexcept
Get or create the timer event-loop.
Definition loop_intf.hpp:163
auto async_function(auto &&func) noexcept
Call a function from the loop.
Definition loop_intf.hpp:225
timer_callback_token delay_function(utc_nanoseconds time_point, auto &&func) noexcept
Call a function at a certain time.
Definition loop_intf.hpp:236
void set_vsync_monitor_id(uintptr_t id) noexcept
Set the monitor id for vertical sync.
Definition loop_intf.hpp:186
int resume(std::stop_token stop_token={}) noexcept
Resume the loop on the current thread.
Definition loop_intf.hpp:324
void set_maximum_frame_rate(double frame_rate) noexcept
Set maximum frame rate.
Definition loop_intf.hpp:178
void subscribe_render(std::weak_ptr< render_callback_type > f) noexcept
Subscribe a render function to be called on vsync.
Definition loop_intf.hpp:270
void wfree_post_function(auto &&func) noexcept
Wait-free post a function to be called from the loop.
Definition loop_intf.hpp:201
void post_function(auto &&func) noexcept
Post a function to be called from the loop.
Definition loop_intf.hpp:212
timer_callback_token repeat_function(std::chrono::nanoseconds period, auto &&func) noexcept
Call a function repeatedly.
Definition loop_intf.hpp:260
static hi_no_inline loop & main() noexcept
Get or create the main-loop.
Definition loop_intf.hpp:141
void remove_socket(int fd)
Remove the callback associated with a socket.
Definition loop_intf.hpp:311
render_callback_token subscribe_render(F &&f) noexcept
Subscribe a render function to be called on vsync.
Definition loop_intf.hpp:281
void add_socket(int fd, socket_event event_mask, std::function< void(int, socket_events const &)> f)
Add a callback that reacts on a socket.
Definition loop_intf.hpp:301
timer_callback_token repeat_function(std::chrono::nanoseconds period, utc_nanoseconds time_point, auto &&func) noexcept
Call a function repeatedly.
Definition loop_intf.hpp:249
Definition loop_intf.hpp:28
Definition socket_event_intf.hpp:74