EventLoopImplementationQt.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. /*
  2. * Copyright (c) 2022-2023, Andreas Kling <kling@serenityos.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. static void qt_timer_fired(Core::TimerShouldFireWhenNotVisible should_fire_when_not_visible, Core::EventReceiver& object)
  186. {
  187. if (should_fire_when_not_visible == Core::TimerShouldFireWhenNotVisible::No) {
  188. if (!object.is_visible_for_timer_purposes())
  189. return;
  190. }
  191. Core::TimerEvent event;
  192. object.dispatch_event(event);
  193. }
  194. intptr_t EventLoopManagerQt::register_timer(Core::EventReceiver& object, int milliseconds, bool should_reload, Core::TimerShouldFireWhenNotVisible should_fire_when_not_visible)
  195. {
  196. auto timer = new QTimer;
  197. timer->setTimerType(Qt::PreciseTimer);
  198. timer->setInterval(milliseconds);
  199. timer->setSingleShot(!should_reload);
  200. auto weak_object = object.make_weak_ptr();
  201. QObject::connect(timer, &QTimer::timeout, [should_fire_when_not_visible, weak_object = move(weak_object)] {
  202. auto object = weak_object.strong_ref();
  203. if (!object)
  204. return;
  205. qt_timer_fired(should_fire_when_not_visible, *object);
  206. });
  207. timer->start();
  208. return bit_cast<intptr_t>(timer);
  209. }
  210. void EventLoopManagerQt::unregister_timer(intptr_t timer_id)
  211. {
  212. auto* timer = bit_cast<QTimer*>(timer_id);
  213. delete timer;
  214. }
  215. static void qt_notifier_activated(Core::Notifier& notifier)
  216. {
  217. Core::NotifierActivationEvent event(notifier.fd(), notifier.type());
  218. notifier.dispatch_event(event);
  219. }
  220. void EventLoopManagerQt::register_notifier(Core::Notifier& notifier)
  221. {
  222. QSocketNotifier::Type type;
  223. switch (notifier.type()) {
  224. case Core::Notifier::Type::Read:
  225. type = QSocketNotifier::Read;
  226. break;
  227. case Core::Notifier::Type::Write:
  228. type = QSocketNotifier::Write;
  229. break;
  230. default:
  231. TODO();
  232. }
  233. auto socket_notifier = make<QSocketNotifier>(notifier.fd(), type);
  234. QObject::connect(socket_notifier, &QSocketNotifier::activated, [&notifier] {
  235. qt_notifier_activated(notifier);
  236. });
  237. ThreadData::the().notifiers.set(&notifier, move(socket_notifier));
  238. }
  239. void EventLoopManagerQt::unregister_notifier(Core::Notifier& notifier)
  240. {
  241. ThreadData::the().notifiers.remove(&notifier);
  242. }
  243. void EventLoopManagerQt::handle_signal(int signal_number)
  244. {
  245. auto& that = static_cast<EventLoopManagerQt&>(Core::EventLoopManager::the());
  246. // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425
  247. // Apparently warn_unused_result ignoring (void) casts is a feature
  248. [[maybe_unused]] auto _ = ::write(that.m_signal_socket_fds[1], &signal_number, sizeof(signal_number));
  249. }
  250. int EventLoopManagerQt::register_signal(int signal_number, Function<void(int)> handler)
  251. {
  252. VERIFY(signal_number != 0);
  253. auto& info = *signals_info();
  254. auto handlers = info.signal_handlers.find(signal_number);
  255. if (handlers == info.signal_handlers.end()) {
  256. auto signal_handlers = adopt_ref(*new SignalHandlers(signal_number, EventLoopManagerQt::handle_signal));
  257. auto handler_id = signal_handlers->add(move(handler));
  258. info.signal_handlers.set(signal_number, move(signal_handlers));
  259. return handler_id;
  260. } else {
  261. return handlers->value->add(move(handler));
  262. }
  263. }
  264. void EventLoopManagerQt::unregister_signal(int handler_id)
  265. {
  266. VERIFY(handler_id != 0);
  267. int remove_signal_number = 0;
  268. auto& info = *signals_info();
  269. for (auto& h : info.signal_handlers) {
  270. auto& handlers = *h.value;
  271. if (handlers.remove(handler_id)) {
  272. if (handlers.is_empty())
  273. remove_signal_number = handlers.m_signal_number;
  274. break;
  275. }
  276. }
  277. if (remove_signal_number != 0)
  278. info.signal_handlers.remove(remove_signal_number);
  279. }
  280. void EventLoopManagerQt::did_post_event()
  281. {
  282. QCoreApplication::postEvent(m_main_thread_event_target.ptr(), new QtEventLoopManagerEvent(QtEventLoopManagerEvent::process_event_queue_event_type()));
  283. }
  284. bool EventLoopManagerQt::event_target_received_event(Badge<EventLoopImplementationQtEventTarget>, QEvent* event)
  285. {
  286. if (event->type() == QtEventLoopManagerEvent::process_event_queue_event_type()) {
  287. Core::ThreadEventQueue::current().process();
  288. return true;
  289. }
  290. return false;
  291. }
  292. EventLoopManagerQt::EventLoopManagerQt()
  293. : m_main_thread_event_target(make<EventLoopImplementationQtEventTarget>())
  294. {
  295. MUST(Core::System::socketpair(AF_LOCAL, SOCK_STREAM, 0, m_signal_socket_fds));
  296. m_signal_socket_notifier = new QSocketNotifier(m_signal_socket_fds[0], QSocketNotifier::Read);
  297. QObject::connect(m_signal_socket_notifier, &QSocketNotifier::activated, [this] {
  298. int signal_number = {};
  299. ssize_t nread;
  300. do {
  301. errno = 0;
  302. nread = read(this->m_signal_socket_fds[0], &signal_number, sizeof(signal_number));
  303. if (nread >= 0)
  304. break;
  305. } while (errno == EINTR);
  306. VERIFY(nread == sizeof(signal_number));
  307. dispatch_signal(signal_number);
  308. });
  309. m_signal_socket_notifier->setEnabled(true);
  310. }
  311. EventLoopManagerQt::~EventLoopManagerQt()
  312. {
  313. delete m_signal_socket_notifier;
  314. ::close(m_signal_socket_fds[0]);
  315. ::close(m_signal_socket_fds[1]);
  316. }
  317. NonnullOwnPtr<Core::EventLoopImplementation> EventLoopManagerQt::make_implementation()
  318. {
  319. return adopt_own(*new EventLoopImplementationQt);
  320. }
  321. }