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
Родитель 5bbb41415a
Коммит 41ff753339
3 изменённых файлов: 33 добавлений и 14 удалений

Просмотреть файл

@ -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',

Просмотреть файл

@ -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<NodeBindingsMac*>(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();
}
}

Просмотреть файл

@ -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_;