blob: e1e4e0854e900d01588b866cfe601dc8c4da68ef [file] [log] [blame]
Parker Schuhd7db83d2017-02-08 20:49:15 -08001#include <gdk/gdk.h>
Parker Schuh309dd722017-02-25 11:31:18 -08002#include <gtk/gtk.h>
Parker Schuhd7db83d2017-02-08 20:49:15 -08003#include <sys/epoll.h>
Austin Schuh60e77942022-05-16 17:48:24 -07004
Parker Schuhd7db83d2017-02-08 20:49:15 -08005#include <condition_variable>
Parker Schuh309dd722017-02-25 11:31:18 -08006#include <mutex>
7#include <thread>
Parker Schuhd7db83d2017-02-08 20:49:15 -08008
Brian Silverman58899fd2019-03-24 11:03:11 -07009#include "aos/logging/logging.h"
Austin Schuh60e77942022-05-16 17:48:24 -070010#include "aos/vision/events/epoll_events.h"
Parker Schuhd7db83d2017-02-08 20:49:15 -080011
12namespace aos {
13namespace events {
14
15void EpollLoop::RunWithGtkMain() {
16 int timeout;
17 static constexpr size_t kNumberOfEvents = 64;
18 epoll_event events[kNumberOfEvents];
19 int number_events = 0;
20
21 std::mutex m;
22 std::condition_variable cv;
23 bool all_events_handled = false;
24 auto handle_cb = [&]() {
25 {
26 std::unique_lock<std::mutex> lk(m);
27
28 for (int i = 0; i < number_events; i++) {
29 EpollEvent *event = static_cast<EpollEvent *>(events[i].data.ptr);
30 if ((events[i].events & ~(EPOLLIN | EPOLLPRI)) != 0) {
Austin Schuhf257f3c2019-10-27 21:00:43 -070031 AOS_LOG(FATAL, "unexpected epoll events set in %x on %d\n",
32 events[i].events, event->fd());
Parker Schuhd7db83d2017-02-08 20:49:15 -080033 }
34 event->ReadEvent();
35 }
36 timeout = CalculateTimeout();
37
38 all_events_handled = true;
39 }
40 cv.notify_one();
41 };
42 handle_cb();
43 using HandleCBType = decltype(handle_cb);
44
45 std::thread t([&]() {
46 std::unique_lock<std::mutex> lk(m);
47 while (true) {
Parker Schuh309dd722017-02-25 11:31:18 -080048 cv.wait(lk, [&all_events_handled] { return all_events_handled; });
Parker Schuhd7db83d2017-02-08 20:49:15 -080049 // Wait for handle_cb to be done.
Parker Schuh309dd722017-02-25 11:31:18 -080050 number_events =
51 PCHECK(epoll_wait(epoll_fd(), events, kNumberOfEvents, timeout));
Parker Schuhd7db83d2017-02-08 20:49:15 -080052 all_events_handled = false;
53 // Trigger handle_cb on main_thread to avoid concurrency.
Parker Schuh309dd722017-02-25 11:31:18 -080054 gdk_threads_add_idle(
55 +[](gpointer user_data) -> gboolean {
56 auto &handle_cb = *reinterpret_cast<HandleCBType *>(user_data);
57 handle_cb();
58 return G_SOURCE_REMOVE;
59 },
60 &handle_cb);
Parker Schuhd7db83d2017-02-08 20:49:15 -080061 }
62 });
63 gtk_main();
64
65 // TODO(parker): Allow concurrent proxy onto the normal thread just like Gtk
66 // in order to allow event loop fusion, and make event addition thread-safe.
67
68 // Avoid stack destructors (explicitly shutting down of the thread.)
69 exit(EXIT_SUCCESS);
70}
71
72} // namespace events
73} // namespace aos