From eb9673a1529348e76a4b14ea4c5fbb2f95659493 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 21 Feb 2014 13:21:02 +0800 Subject: [PATCH] linux: Implement libuv message loop polling. --- common/node_bindings_linux.cc | 35 ++++++++++++++++++++++++++++++++++- common/node_bindings_linux.h | 8 ++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/common/node_bindings_linux.cc b/common/node_bindings_linux.cc index 4f8ad9903a31..035441c8dc37 100644 --- a/common/node_bindings_linux.cc +++ b/common/node_bindings_linux.cc @@ -4,16 +4,49 @@ #include "common/node_bindings_linux.h" +#include + namespace atom { NodeBindingsLinux::NodeBindingsLinux(bool is_browser) - : NodeBindings(is_browser) { + : NodeBindings(is_browser), + epoll_(epoll_create(1)) { + int backend_fd = uv_backend_fd(uv_loop_); + struct epoll_event ev = { 0 }; + ev.events = EPOLLIN; + ev.data.fd = backend_fd; + epoll_ctl(epoll_, EPOLL_CTL_ADD, backend_fd, &ev); } NodeBindingsLinux::~NodeBindingsLinux() { } +void NodeBindingsLinux::RunMessageLoop() { + // Get notified when libuv's watcher queue changes. + uv_loop_->data = this; + uv_loop_->on_watcher_queue_updated = OnWatcherQueueChanged; + + NodeBindings::RunMessageLoop(); +} + +// static +void NodeBindingsLinux::OnWatcherQueueChanged(uv_loop_t* loop) { + NodeBindingsLinux* self = static_cast(loop->data); + + // We need to break the io polling in the epoll thread when loop's watcher + // queue changes, otherwise new events cannot be notified. + self->WakeupEmbedThread(); +} + void NodeBindingsLinux::PollEvents() { + int timeout = uv_backend_timeout(uv_loop_); + + // Wait for new libuv events. + int r; + do { + struct epoll_event ev; + r = epoll_wait(epoll_, &ev, 1, timeout); + } while (r == -1 && errno == EINTR); } // static diff --git a/common/node_bindings_linux.h b/common/node_bindings_linux.h index b4a294144c4f..83711543d80f 100644 --- a/common/node_bindings_linux.h +++ b/common/node_bindings_linux.h @@ -15,9 +15,17 @@ class NodeBindingsLinux : public NodeBindings { explicit NodeBindingsLinux(bool is_browser); virtual ~NodeBindingsLinux(); + virtual void RunMessageLoop() OVERRIDE; + private: + // Called when uv's watcher queue changes. + static void OnWatcherQueueChanged(uv_loop_t* loop); + virtual void PollEvents() OVERRIDE; + // Epoll to poll for uv's backend fd. + int epoll_; + DISALLOW_COPY_AND_ASSIGN(NodeBindingsLinux); };