Don't use gcd to post tasks to main thread.

This commit is contained in:
Cheng Zhao 2013-07-22 13:02:02 +08:00
parent 5bbb41415a
commit 41ff753339
3 changed files with 33 additions and 14 deletions

View file

@ -130,8 +130,8 @@
'common/api/object_life_monitor.h', 'common/api/object_life_monitor.h',
'common/node_bindings.cc', 'common/node_bindings.cc',
'common/node_bindings.h', 'common/node_bindings.h',
'common/node_bindings_mac.cc',
'common/node_bindings_mac.h', 'common/node_bindings_mac.h',
'common/node_bindings_mac.mm',
'common/options_switches.cc', 'common/options_switches.cc',
'common/options_switches.h', 'common/options_switches.h',
'common/platform_util.h', 'common/platform_util.h',

View file

@ -26,7 +26,8 @@ void UvNoOp(uv_async_t* handle, int status) {
NodeBindingsMac::NodeBindingsMac(bool is_browser) NodeBindingsMac::NodeBindingsMac(bool is_browser)
: NodeBindings(is_browser), : NodeBindings(is_browser),
loop_(uv_default_loop()), message_loop_(NULL),
uv_loop_(uv_default_loop()),
kqueue_(kqueue()), kqueue_(kqueue()),
embed_closed_(false) { embed_closed_(false) {
} }
@ -43,7 +44,7 @@ void NodeBindingsMac::PrepareMessageLoop() {
// Add dummy handle for libuv, otherwise libuv would quit when there is // Add dummy handle for libuv, otherwise libuv would quit when there is
// nothing to do. // 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. // Start worker that will interrupt main loop when having uv events.
uv_sem_init(&embed_sem_, 0); uv_sem_init(&embed_sem_, 0);
@ -53,8 +54,12 @@ void NodeBindingsMac::PrepareMessageLoop() {
void NodeBindingsMac::RunMessageLoop() { void NodeBindingsMac::RunMessageLoop() {
DCHECK(!is_browser_ || BrowserThread::CurrentlyOn(BrowserThread::UI)); DCHECK(!is_browser_ || BrowserThread::CurrentlyOn(BrowserThread::UI));
loop_->data = this; // The MessageLoop should have been created, remember the one in main thread.
loop_->on_watcher_queue_updated = OnWatcherQueueChanged; 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. // Run uv loop for once to give the uv__io_poll a chance to add all events.
UvRunOnce(); UvRunOnce();
@ -68,18 +73,24 @@ void NodeBindingsMac::UvRunOnce() {
v8::Context::Scope context_scope(node::g_context); v8::Context::Scope context_scope(node::g_context);
// Deal with uv events. // Deal with uv events.
int r = uv_run(loop_, (uv_run_mode)(UV_RUN_ONCE | UV_RUN_NOWAIT)); int r = uv_run(uv_loop_, (uv_run_mode)(UV_RUN_ONCE | UV_RUN_NOWAIT));
if (r == 0 || loop_->stop_flag != 0) if (r == 0 || uv_loop_->stop_flag != 0)
MessageLoop::current()->QuitWhenIdle(); // Quit from uv. message_loop_->QuitWhenIdle(); // Quit from uv.
// Tell the worker thread to continue polling. // Tell the worker thread to continue polling.
uv_sem_post(&embed_sem_); 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) { void NodeBindingsMac::EmbedThreadRunner(void *arg) {
NodeBindingsMac* self = static_cast<NodeBindingsMac*>(arg); NodeBindingsMac* self = static_cast<NodeBindingsMac*>(arg);
uv_loop_t* loop = self->loop_; uv_loop_t* loop = self->uv_loop_;
// Add uv's backend fd to kqueue. // Add uv's backend fd to kqueue.
struct kevent ev; struct kevent ev;
@ -105,9 +116,7 @@ void NodeBindingsMac::EmbedThreadRunner(void *arg) {
} while (r == -1 && errno == EINTR); } while (r == -1 && errno == EINTR);
// Deal with event in main thread. // Deal with event in main thread.
dispatch_async(dispatch_get_main_queue(), ^{ self->WakeupMainThread();
self->UvRunOnce();
});
} }
} }

View file

@ -9,6 +9,10 @@
#include "common/node_bindings.h" #include "common/node_bindings.h"
#include "vendor/node/deps/uv/include/uv.h" #include "vendor/node/deps/uv/include/uv.h"
namespace base {
class MessageLoop;
}
namespace atom { namespace atom {
class NodeBindingsMac : public NodeBindings { class NodeBindingsMac : public NodeBindings {
@ -23,14 +27,20 @@ class NodeBindingsMac : public NodeBindings {
// Run the libuv loop for once. // Run the libuv loop for once.
void UvRunOnce(); void UvRunOnce();
// Make the main thread run libuv loop.
void WakeupMainThread();
// Thread to poll uv events. // Thread to poll uv events.
static void EmbedThreadRunner(void *arg); static void EmbedThreadRunner(void *arg);
// Called when uv's watcher queue changes. // Called when uv's watcher queue changes.
static void OnWatcherQueueChanged(uv_loop_t* loop); static void OnWatcherQueueChanged(uv_loop_t* loop);
// Main thread's loop. // Main thread's MessageLoop.
uv_loop_t* loop_; base::MessageLoop* message_loop_;
// Main thread's libuv loop.
uv_loop_t* uv_loop_;
// Kqueue to poll for uv's backend fd. // Kqueue to poll for uv's backend fd.
int kqueue_; int kqueue_;