blob: 4ff9fde11855f94561f7de45f42b0dcd261ba9e7 [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>
Parker Schuhd7db83d2017-02-08 20:49:15 -08004#include <condition_variable>
Parker Schuh309dd722017-02-25 11:31:18 -08005#include <mutex>
6#include <thread>
Parker Schuhd7db83d2017-02-08 20:49:15 -08007
8#include "aos/vision/events/epoll_events.h"
Brian Silverman58899fd2019-03-24 11:03:11 -07009#include "aos/logging/logging.h"
Parker Schuhd7db83d2017-02-08 20:49:15 -080010
11namespace aos {
12namespace events {
13
14void EpollLoop::RunWithGtkMain() {
15 int timeout;
16 static constexpr size_t kNumberOfEvents = 64;
17 epoll_event events[kNumberOfEvents];
18 int number_events = 0;
19
20 std::mutex m;
21 std::condition_variable cv;
22 bool all_events_handled = false;
23 auto handle_cb = [&]() {
24 {
25 std::unique_lock<std::mutex> lk(m);
26
27 for (int i = 0; i < number_events; i++) {
28 EpollEvent *event = static_cast<EpollEvent *>(events[i].data.ptr);
29 if ((events[i].events & ~(EPOLLIN | EPOLLPRI)) != 0) {
30 LOG(FATAL, "unexpected epoll events set in %x on %d\n",
31 events[i].events, event->fd());
32 }
33 event->ReadEvent();
34 }
35 timeout = CalculateTimeout();
36
37 all_events_handled = true;
38 }
39 cv.notify_one();
40 };
41 handle_cb();
42 using HandleCBType = decltype(handle_cb);
43
44 std::thread t([&]() {
45 std::unique_lock<std::mutex> lk(m);
46 while (true) {
Parker Schuh309dd722017-02-25 11:31:18 -080047 cv.wait(lk, [&all_events_handled] { return all_events_handled; });
Parker Schuhd7db83d2017-02-08 20:49:15 -080048 // Wait for handle_cb to be done.
Parker Schuh309dd722017-02-25 11:31:18 -080049 number_events =
50 PCHECK(epoll_wait(epoll_fd(), events, kNumberOfEvents, timeout));
Parker Schuhd7db83d2017-02-08 20:49:15 -080051 all_events_handled = false;
52 // Trigger handle_cb on main_thread to avoid concurrency.
Parker Schuh309dd722017-02-25 11:31:18 -080053 gdk_threads_add_idle(
54 +[](gpointer user_data) -> gboolean {
55 auto &handle_cb = *reinterpret_cast<HandleCBType *>(user_data);
56 handle_cb();
57 return G_SOURCE_REMOVE;
58 },
59 &handle_cb);
Parker Schuhd7db83d2017-02-08 20:49:15 -080060 }
61 });
62 gtk_main();
63
64 // TODO(parker): Allow concurrent proxy onto the normal thread just like Gtk
65 // in order to allow event loop fusion, and make event addition thread-safe.
66
67 // Avoid stack destructors (explicitly shutting down of the thread.)
68 exit(EXIT_SUCCESS);
69}
70
71} // namespace events
72} // namespace aos