9#ifndef STLAB_CONCURRENCY_MAIN_EXECUTOR_HPP
10#define STLAB_CONCURRENCY_MAIN_EXECUTOR_HPP
23#include <stlab/config.hpp>
25#if STLAB_MAIN_EXECUTOR(QT5) || STLAB_MAIN_EXECUTOR(QT6)
27#if (STLAB_MAIN_EXECUTOR(QT5) && \
28 (QT_VERSION < QT_VERSION_CHECK(5, 0, 0) || QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)) || \
29 STLAB_MAIN_EXECUTOR(QT6) && \
30 (QT_VERSION < QT_VERSION_CHECK(6, 0, 0) || QT_VERSION >= QT_VERSION_CHECK(7, 0, 0)))
31#error "Mismatching Qt versions"
33#include <QCoreApplication>
37#elif STLAB_MAIN_EXECUTOR(LIBDISPATCH)
38#include <dispatch/dispatch.h>
39#elif STLAB_MAIN_EXECUTOR(EMSCRIPTEN)
46STLAB_VERSION_NAMESPACE_BEGIN()
60#if STLAB_MAIN_EXECUTOR(QT5) || STLAB_MAIN_EXECUTOR(QT6)
62class main_executor_type {
63 using result_type = void;
65 struct event_receiver;
67 class executor_event :
public QEvent {
69 std::unique_ptr<event_receiver> _receiver;
72 executor_event() : QEvent(QEvent::User), _receiver(new event_receiver()) {
73 _receiver->moveToThread(QCoreApplication::instance()->thread());
77 void set_task(F&& f) {
78 _f = std::forward<F>(f);
81 void execute() { _f(); }
83 QObject* receiver()
const {
return _receiver.get(); }
86 struct event_receiver :
public QObject {
87 bool event(QEvent* event)
override {
88 auto myEvent =
dynamic_cast<executor_event*
>(event);
99 auto operator()(F f)
const -> std::enable_if_t<std::is_nothrow_invocable_v<F>> {
100 auto event = std::make_unique<executor_event>();
101 event->set_task(std::move(f));
102 auto receiver =
event->receiver();
103 QCoreApplication::postEvent(receiver, event.release());
109#elif STLAB_MAIN_EXECUTOR(LIBDISPATCH)
111struct main_executor_type {
112 using result_type = void;
114 template <
typename F>
115 auto operator()(F f)
const -> std::enable_if_t<std::is_nothrow_invocable_v<F>> {
116 using f_t =
decltype(f);
118 dispatch_async_f(dispatch_get_main_queue(),
new f_t(std::move(f)), [](
void* f_) {
119 auto f =
static_cast<f_t*
>(f_);
126#elif STLAB_MAIN_EXECUTOR(EMSCRIPTEN)
128struct main_executor_type {
129 using result_type = void;
132 auto operator()(F&& f)
const -> std::enable_if_t<std::is_nothrow_invocable_v<F>> {
133 using function_type =
typename std::remove_reference<F>::type;
134 auto p =
new function_type(std::forward<F>(f));
151 emscripten_async_run_in_main_runtime_thread(
152 EM_FUNC_SIG_VI,
static_cast<void (*)(
void*)
>([](
void* f_) {
153 emscripten_async_call(
155 auto f =
static_cast<function_type*
>(f_);
168#elif STLAB_MAIN_EXECUTOR(NONE)
171struct main_executor_type {
172 using result_type = void;
174 template <
typename F>
175 void operator()(F f)
const {}
193STLAB_VERSION_NAMESPACE_END()
Thread-pool executors mapping to the OS scheduler (libdispatch, Windows pool, portable).
constexpr auto main_executor
Runs void() noexcept tasks on the process main thread (Qt, libdispatch, or Emscripten as configured).
Definition main_executor.hpp:187
typename noexcept_deducer< task_, F >::type task
task_ with noexcept deduced from the function type F (e.g. void() vs void() noexcept).
Definition task.hpp:324
Definition reverse.hpp:28
Move-only callable wrapper for executor scheduling (task<Signature>).