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