diff --git a/atom.gyp b/atom.gyp index 875332ec4032..384680167220 100644 --- a/atom.gyp +++ b/atom.gyp @@ -130,8 +130,8 @@ 'common/api/object_life_monitor.h', 'common/node_bindings.cc', 'common/node_bindings.h', + 'common/node_bindings_mac.cc', 'common/node_bindings_mac.h', - 'common/node_bindings_mac.mm', 'common/options_switches.cc', 'common/options_switches.h', 'common/platform_util.h', diff --git a/common/node_bindings_mac.mm b/common/node_bindings_mac.cc similarity index 79% rename from common/node_bindings_mac.mm rename to common/node_bindings_mac.cc index f7a7585f48ee..5db27a60d4f5 100644 --- a/common/node_bindings_mac.mm +++ b/common/node_bindings_mac.cc @@ -26,7 +26,8 @@ void UvNoOp(uv_async_t* handle, int status) { NodeBindingsMac::NodeBindingsMac(bool is_browser) : NodeBindings(is_browser), - loop_(uv_default_loop()), + message_loop_(NULL), + uv_loop_(uv_default_loop()), kqueue_(kqueue()), embed_closed_(false) { } @@ -43,7 +44,7 @@ void NodeBindingsMac::PrepareMessageLoop() { // Add dummy handle for libuv, otherwise libuv would quit when there is // nothing to do. - uv_async_init(loop_, &dummy_uv_handle_, UvNoOp); + uv_async_init(uv_loop_, &dummy_uv_handle_, UvNoOp); // Start worker that will interrupt main loop when having uv events. uv_sem_init(&embed_sem_, 0); @@ -53,8 +54,12 @@ void NodeBindingsMac::PrepareMessageLoop() { void NodeBindingsMac::RunMessageLoop() { DCHECK(!is_browser_ || BrowserThread::CurrentlyOn(BrowserThread::UI)); - loop_->data = this; - loop_->on_watcher_queue_updated = OnWatcherQueueChanged; + // The MessageLoop should have been created, remember the one in main thread. + message_loop_ = base::MessageLoop::current(); + + // Get notified when libuv's watcher queue changes. + uv_loop_->data = this; + uv_loop_->on_watcher_queue_updated = OnWatcherQueueChanged; // Run uv loop for once to give the uv__io_poll a chance to add all events. UvRunOnce(); @@ -68,18 +73,24 @@ void NodeBindingsMac::UvRunOnce() { v8::Context::Scope context_scope(node::g_context); // Deal with uv events. - int r = uv_run(loop_, (uv_run_mode)(UV_RUN_ONCE | UV_RUN_NOWAIT)); - if (r == 0 || loop_->stop_flag != 0) - MessageLoop::current()->QuitWhenIdle(); // Quit from uv. + int r = uv_run(uv_loop_, (uv_run_mode)(UV_RUN_ONCE | UV_RUN_NOWAIT)); + if (r == 0 || uv_loop_->stop_flag != 0) + message_loop_->QuitWhenIdle(); // Quit from uv. // Tell the worker thread to continue polling. uv_sem_post(&embed_sem_); } +void NodeBindingsMac::WakeupMainThread() { + DCHECK(message_loop_); + message_loop_->PostTask(FROM_HERE, base::Bind(&NodeBindingsMac::UvRunOnce, + base::Unretained(this))); +} + void NodeBindingsMac::EmbedThreadRunner(void *arg) { NodeBindingsMac* self = static_cast(arg); - uv_loop_t* loop = self->loop_; + uv_loop_t* loop = self->uv_loop_; // Add uv's backend fd to kqueue. struct kevent ev; @@ -105,9 +116,7 @@ void NodeBindingsMac::EmbedThreadRunner(void *arg) { } while (r == -1 && errno == EINTR); // Deal with event in main thread. - dispatch_async(dispatch_get_main_queue(), ^{ - self->UvRunOnce(); - }); + self->WakeupMainThread(); } } diff --git a/common/node_bindings_mac.h b/common/node_bindings_mac.h index 6380794ea3cd..2e8c3e04e80c 100644 --- a/common/node_bindings_mac.h +++ b/common/node_bindings_mac.h @@ -9,6 +9,10 @@ #include "common/node_bindings.h" #include "vendor/node/deps/uv/include/uv.h" +namespace base { +class MessageLoop; +} + namespace atom { class NodeBindingsMac : public NodeBindings { @@ -23,14 +27,20 @@ class NodeBindingsMac : public NodeBindings { // Run the libuv loop for once. void UvRunOnce(); + // Make the main thread run libuv loop. + void WakeupMainThread(); + // Thread to poll uv events. static void EmbedThreadRunner(void *arg); // Called when uv's watcher queue changes. static void OnWatcherQueueChanged(uv_loop_t* loop); - // Main thread's loop. - uv_loop_t* loop_; + // Main thread's MessageLoop. + base::MessageLoop* message_loop_; + + // Main thread's libuv loop. + uv_loop_t* uv_loop_; // Kqueue to poll for uv's backend fd. int kqueue_;