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);
20namespace hi::inline
v1 {
24 using timer_callback_token = function_timer<>::callback_token;
25 using render_callback_type =
std::function<void(utc_nanoseconds)>;
32 impl_type() : _thread_id(current_thread_id()) {}
34 virtual ~impl_type() {}
35 impl_type(impl_type
const&) =
delete;
36 impl_type(impl_type&&) =
delete;
37 impl_type& operator=(impl_type
const&) =
delete;
38 impl_type& operator=(impl_type&&) =
delete;
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));
61 timer_callback_token delay_function(utc_nanoseconds time_point,
auto&& func)
noexcept
63 auto [token, first_to_call] = _function_timer.delay_function(time_point, hi_forward(func));
71 timer_callback_token repeat_function(
std::chrono::nanoseconds period, utc_nanoseconds time_point,
auto&& func)
noexcept
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
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));
236 [[nodiscard]] timer_callback_token
delay_function(utc_nanoseconds time_point,
auto&& func)
noexcept
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);
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) {
367 set_thread_name(
"timer");
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();
388 inline static thread_local std::unique_ptr<loop> _local;
392 inline static std::atomic<loop *> _main;
396 inline static std::atomic<loop *> _timer;
398 inline static std::jthread _timer_thread;
400 std::unique_ptr<impl_type> _pimpl;
403template<
typename Result,
typename... Args>
405void notifier<Result(Args...)>::loop_local_post_function(F&& f)
const noexcept
410template<
typename Result,
typename... Args>
412void notifier<Result(Args...)>::loop_main_post_function(F&& f)
const noexcept
417template<
typename Result,
typename... Args>
419void notifier<Result(Args...)>::loop_timer_post_function(F&& f)
const noexcept
DOXYGEN BUG.
Definition algorithm.hpp:16
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
static hi_no_inline loop & local() noexcept
Get or create the thread-local loop.
Definition loop_intf.hpp:128
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
loop()
Construct a loop.
Definition loop_win32_impl.hpp:636
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 socket_event_intf.hpp:74