Skip to content

Commit

Permalink
Don't use gcd to post tasks to main thread.
Browse files Browse the repository at this point in the history
  • Loading branch information
zcbenz committed Jul 22, 2013
1 parent 5bbb414 commit 41ff753
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 14 deletions.
2 changes: 1 addition & 1 deletion atom.gyp
Original file line number Diff line number Diff line change
Expand Up @@ -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',
Expand Down
31 changes: 20 additions & 11 deletions common/node_bindings_mac.mm → common/node_bindings_mac.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
}
Expand All @@ -43,7 +44,7 @@ void UvNoOp(uv_async_t* handle, int status) {

// 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);
Expand All @@ -53,8 +54,12 @@ void UvNoOp(uv_async_t* handle, int status) {
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();
Expand All @@ -68,18 +73,24 @@ void UvNoOp(uv_async_t* handle, int status) {
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;
Expand All @@ -105,9 +116,7 @@ void UvNoOp(uv_async_t* handle, int status) {
} while (r == -1 && errno == EINTR);

// Deal with event in main thread.
dispatch_async(dispatch_get_main_queue(), ^{
self->UvRunOnce();
});
self->WakeupMainThread();
}
}

Expand Down
14 changes: 12 additions & 2 deletions common/node_bindings_mac.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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_;
Expand Down

0 comments on commit 41ff753

Please sign in to comment.