EventLoopImplementationQt.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375
  1. /*
  2. * Copyright (c) 2022-2023, Andreas Kling <andreas@ladybird.org>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include "EventLoopImplementationQt.h"
  7. #include "EventLoopImplementationQtEventTarget.h"
  8. #include <AK/IDAllocator.h>
  9. #include <AK/Singleton.h>
  10. #include <AK/TemporaryChange.h>
  11. #include <LibCore/Event.h>
  12. #include <LibCore/EventReceiver.h>
  13. #include <LibCore/Notifier.h>
  14. #include <LibCore/System.h>
  15. #include <LibCore/ThreadEventQueue.h>
  16. #include <QCoreApplication>
  17. #include <QTimer>
  18. namespace Ladybird {
  19. struct ThreadData;
  20. static thread_local ThreadData* s_thread_data;
  21. struct ThreadData {
  22. static ThreadData& the()
  23. {
  24. if (!s_thread_data) {
  25. // FIXME: Don't leak this.
  26. s_thread_data = new ThreadData;
  27. }
  28. return *s_thread_data;
  29. }
  30. HashMap<Core::Notifier*, NonnullOwnPtr<QSocketNotifier>> notifiers;
  31. };
  32. class SignalHandlers : public RefCounted<SignalHandlers> {
  33. AK_MAKE_NONCOPYABLE(SignalHandlers);
  34. AK_MAKE_NONMOVABLE(SignalHandlers);
  35. public:
  36. SignalHandlers(int signal_number, void (*handle_signal)(int));
  37. ~SignalHandlers();
  38. void dispatch();
  39. int add(Function<void(int)>&& handler);
  40. bool remove(int handler_id);
  41. bool is_empty() const
  42. {
  43. if (m_calling_handlers) {
  44. for (auto const& handler : m_handlers_pending) {
  45. if (handler.value)
  46. return false; // an add is pending
  47. }
  48. }
  49. return m_handlers.is_empty();
  50. }
  51. bool have(int handler_id) const
  52. {
  53. if (m_calling_handlers) {
  54. auto it = m_handlers_pending.find(handler_id);
  55. if (it != m_handlers_pending.end()) {
  56. if (!it->value)
  57. return false; // a deletion is pending
  58. }
  59. }
  60. return m_handlers.contains(handler_id);
  61. }
  62. int m_signal_number;
  63. void (*m_original_handler)(int);
  64. HashMap<int, Function<void(int)>> m_handlers;
  65. HashMap<int, Function<void(int)>> m_handlers_pending;
  66. bool m_calling_handlers { false };
  67. };
  68. SignalHandlers::SignalHandlers(int signal_number, void (*handle_signal)(int))
  69. : m_signal_number(signal_number)
  70. , m_original_handler(signal(signal_number, handle_signal))
  71. {
  72. }
  73. SignalHandlers::~SignalHandlers()
  74. {
  75. (void)::signal(m_signal_number, m_original_handler);
  76. }
  77. struct SignalHandlersInfo {
  78. HashMap<int, NonnullRefPtr<SignalHandlers>> signal_handlers;
  79. int next_signal_id { 0 };
  80. };
  81. static Singleton<SignalHandlersInfo> s_signals;
  82. static SignalHandlersInfo* signals_info()
  83. {
  84. return s_signals.ptr();
  85. }
  86. void SignalHandlers::dispatch()
  87. {
  88. TemporaryChange change(m_calling_handlers, true);
  89. for (auto& handler : m_handlers)
  90. handler.value(m_signal_number);
  91. if (!m_handlers_pending.is_empty()) {
  92. // Apply pending adds/removes
  93. for (auto& handler : m_handlers_pending) {
  94. if (handler.value) {
  95. auto result = m_handlers.set(handler.key, move(handler.value));
  96. VERIFY(result == AK::HashSetResult::InsertedNewEntry);
  97. } else {
  98. m_handlers.remove(handler.key);
  99. }
  100. }
  101. m_handlers_pending.clear();
  102. }
  103. }
  104. int SignalHandlers::add(Function<void(int)>&& handler)
  105. {
  106. int id = ++signals_info()->next_signal_id; // TODO: worry about wrapping and duplicates?
  107. if (m_calling_handlers)
  108. m_handlers_pending.set(id, move(handler));
  109. else
  110. m_handlers.set(id, move(handler));
  111. return id;
  112. }
  113. bool SignalHandlers::remove(int handler_id)
  114. {
  115. VERIFY(handler_id != 0);
  116. if (m_calling_handlers) {
  117. auto it = m_handlers.find(handler_id);
  118. if (it != m_handlers.end()) {
  119. // Mark pending remove
  120. m_handlers_pending.set(handler_id, {});
  121. return true;
  122. }
  123. it = m_handlers_pending.find(handler_id);
  124. if (it != m_handlers_pending.end()) {
  125. if (!it->value)
  126. return false; // already was marked as deleted
  127. it->value = nullptr;
  128. return true;
  129. }
  130. return false;
  131. }
  132. return m_handlers.remove(handler_id);
  133. }
  134. static void dispatch_signal(int signal_number)
  135. {
  136. auto& info = *signals_info();
  137. auto handlers = info.signal_handlers.find(signal_number);
  138. if (handlers != info.signal_handlers.end()) {
  139. // Make sure we bump the ref count while dispatching the handlers!
  140. // This allows a handler to unregister/register while the handlers
  141. // are being called!
  142. auto handler = handlers->value;
  143. handler->dispatch();
  144. }
  145. }
  146. EventLoopImplementationQt::EventLoopImplementationQt()
  147. {
  148. }
  149. EventLoopImplementationQt::~EventLoopImplementationQt() = default;
  150. int EventLoopImplementationQt::exec()
  151. {
  152. if (is_main_loop())
  153. return QCoreApplication::exec();
  154. return m_event_loop.exec();
  155. }
  156. size_t EventLoopImplementationQt::pump(PumpMode mode)
  157. {
  158. auto result = Core::ThreadEventQueue::current().process();
  159. auto qt_mode = mode == PumpMode::WaitForEvents ? QEventLoop::WaitForMoreEvents : QEventLoop::AllEvents;
  160. if (is_main_loop())
  161. QCoreApplication::processEvents(qt_mode);
  162. else
  163. m_event_loop.processEvents(qt_mode);
  164. result += Core::ThreadEventQueue::current().process();
  165. return result;
  166. }
  167. void EventLoopImplementationQt::quit(int code)
  168. {
  169. if (is_main_loop())
  170. QCoreApplication::exit(code);
  171. else
  172. m_event_loop.exit(code);
  173. }
  174. void EventLoopImplementationQt::wake()
  175. {
  176. if (!is_main_loop())
  177. m_event_loop.wakeUp();
  178. }
  179. void EventLoopImplementationQt::post_event(Core::EventReceiver& receiver, NonnullOwnPtr<Core::Event>&& event)
  180. {
  181. m_thread_event_queue.post_event(receiver, move(event));
  182. if (&m_thread_event_queue != &Core::ThreadEventQueue::current())
  183. wake();
  184. }
  185. void EventLoopImplementationQt::set_main_loop()
  186. {
  187. m_main_loop = true;
  188. auto& event_loop_manager = static_cast<EventLoopManagerQt&>(Core::EventLoopManager::the());
  189. event_loop_manager.set_main_loop_signal_notifiers({});
  190. }
  191. static void qt_timer_fired(Core::TimerShouldFireWhenNotVisible should_fire_when_not_visible, Core::EventReceiver& object)
  192. {
  193. if (should_fire_when_not_visible == Core::TimerShouldFireWhenNotVisible::No) {
  194. if (!object.is_visible_for_timer_purposes())
  195. return;
  196. }
  197. Core::TimerEvent event;
  198. object.dispatch_event(event);
  199. }
  200. intptr_t EventLoopManagerQt::register_timer(Core::EventReceiver& object, int milliseconds, bool should_reload, Core::TimerShouldFireWhenNotVisible should_fire_when_not_visible)
  201. {
  202. auto timer = new QTimer;
  203. timer->setTimerType(Qt::PreciseTimer);
  204. timer->setInterval(milliseconds);
  205. timer->setSingleShot(!should_reload);
  206. auto weak_object = object.make_weak_ptr();
  207. QObject::connect(timer, &QTimer::timeout, [should_fire_when_not_visible, weak_object = move(weak_object)] {
  208. auto object = weak_object.strong_ref();
  209. if (!object)
  210. return;
  211. qt_timer_fired(should_fire_when_not_visible, *object);
  212. });
  213. timer->start();
  214. return bit_cast<intptr_t>(timer);
  215. }
  216. void EventLoopManagerQt::unregister_timer(intptr_t timer_id)
  217. {
  218. auto* timer = bit_cast<QTimer*>(timer_id);
  219. delete timer;
  220. }
  221. static void qt_notifier_activated(Core::Notifier& notifier)
  222. {
  223. Core::NotifierActivationEvent event(notifier.fd(), notifier.type());
  224. notifier.dispatch_event(event);
  225. }
  226. void EventLoopManagerQt::register_notifier(Core::Notifier& notifier)
  227. {
  228. QSocketNotifier::Type type;
  229. switch (notifier.type()) {
  230. case Core::Notifier::Type::Read:
  231. type = QSocketNotifier::Read;
  232. break;
  233. case Core::Notifier::Type::Write:
  234. type = QSocketNotifier::Write;
  235. break;
  236. default:
  237. TODO();
  238. }
  239. auto socket_notifier = make<QSocketNotifier>(notifier.fd(), type);
  240. QObject::connect(socket_notifier, &QSocketNotifier::activated, [&notifier] {
  241. qt_notifier_activated(notifier);
  242. });
  243. ThreadData::the().notifiers.set(&notifier, move(socket_notifier));
  244. }
  245. void EventLoopManagerQt::unregister_notifier(Core::Notifier& notifier)
  246. {
  247. ThreadData::the().notifiers.remove(&notifier);
  248. }
  249. void EventLoopManagerQt::handle_signal(int signal_number)
  250. {
  251. auto& that = static_cast<EventLoopManagerQt&>(Core::EventLoopManager::the());
  252. // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425
  253. // Apparently warn_unused_result ignoring (void) casts is a feature
  254. [[maybe_unused]] auto _ = ::write(that.m_signal_socket_fds[1], &signal_number, sizeof(signal_number));
  255. }
  256. int EventLoopManagerQt::register_signal(int signal_number, Function<void(int)> handler)
  257. {
  258. VERIFY(signal_number != 0);
  259. auto& info = *signals_info();
  260. auto handlers = info.signal_handlers.find(signal_number);
  261. if (handlers == info.signal_handlers.end()) {
  262. auto signal_handlers = adopt_ref(*new SignalHandlers(signal_number, EventLoopManagerQt::handle_signal));
  263. auto handler_id = signal_handlers->add(move(handler));
  264. info.signal_handlers.set(signal_number, move(signal_handlers));
  265. return handler_id;
  266. } else {
  267. return handlers->value->add(move(handler));
  268. }
  269. }
  270. void EventLoopManagerQt::unregister_signal(int handler_id)
  271. {
  272. VERIFY(handler_id != 0);
  273. int remove_signal_number = 0;
  274. auto& info = *signals_info();
  275. for (auto& h : info.signal_handlers) {
  276. auto& handlers = *h.value;
  277. if (handlers.remove(handler_id)) {
  278. if (handlers.is_empty())
  279. remove_signal_number = handlers.m_signal_number;
  280. break;
  281. }
  282. }
  283. if (remove_signal_number != 0)
  284. info.signal_handlers.remove(remove_signal_number);
  285. }
  286. void EventLoopManagerQt::did_post_event()
  287. {
  288. QCoreApplication::postEvent(m_main_thread_event_target.ptr(), new QtEventLoopManagerEvent(QtEventLoopManagerEvent::process_event_queue_event_type()));
  289. }
  290. bool EventLoopManagerQt::event_target_received_event(Badge<EventLoopImplementationQtEventTarget>, QEvent* event)
  291. {
  292. if (event->type() == QtEventLoopManagerEvent::process_event_queue_event_type()) {
  293. Core::ThreadEventQueue::current().process();
  294. return true;
  295. }
  296. return false;
  297. }
  298. EventLoopManagerQt::EventLoopManagerQt()
  299. : m_main_thread_event_target(make<EventLoopImplementationQtEventTarget>())
  300. {
  301. }
  302. void EventLoopManagerQt::set_main_loop_signal_notifiers(Badge<EventLoopImplementationQt>)
  303. {
  304. MUST(Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, m_signal_socket_fds));
  305. m_signal_socket_notifier = new QSocketNotifier(m_signal_socket_fds[0], QSocketNotifier::Read);
  306. QObject::connect(m_signal_socket_notifier, &QSocketNotifier::activated, [this] {
  307. int signal_number = {};
  308. ssize_t nread;
  309. do {
  310. errno = 0;
  311. nread = read(this->m_signal_socket_fds[0], &signal_number, sizeof(signal_number));
  312. if (nread >= 0)
  313. break;
  314. } while (errno == EINTR);
  315. VERIFY(nread == sizeof(signal_number));
  316. dispatch_signal(signal_number);
  317. });
  318. m_signal_socket_notifier->setEnabled(true);
  319. }
  320. EventLoopManagerQt::~EventLoopManagerQt()
  321. {
  322. delete m_signal_socket_notifier;
  323. ::close(m_signal_socket_fds[0]);
  324. ::close(m_signal_socket_fds[1]);
  325. }
  326. NonnullOwnPtr<Core::EventLoopImplementation> EventLoopManagerQt::make_implementation()
  327. {
  328. return adopt_own(*new EventLoopImplementationQt);
  329. }
  330. }