Browse Source

Call Tick() after coming out of select()

Previously we would only call it before going into select(). This is needed
to fix test/simple/test-next-tick-ordering2.js.
v0.7.4-release
Ryan Dahl 15 years ago
parent
commit
17f3ffa633
  1. 35
      src/node.cc
  2. 8
      test/simple/test-next-tick-ordering2.js

35
src/node.cc

@ -73,7 +73,8 @@ static bool use_debug_agent = false;
static bool debug_wait_connect = false; static bool debug_wait_connect = false;
static int debug_port=5858; static int debug_port=5858;
static ev_prepare next_tick_watcher; static ev_check check_tick_watcher;
static ev_prepare prepare_tick_watcher;
static ev_idle tick_spinner; static ev_idle tick_spinner;
static bool need_tick_cb; static bool need_tick_cb;
static Persistent<String> tick_callback_sym; static Persistent<String> tick_callback_sym;
@ -164,6 +165,11 @@ static void Check(EV_P_ ev_check *watcher, int revents) {
static Handle<Value> NeedTickCallback(const Arguments& args) { static Handle<Value> NeedTickCallback(const Arguments& args) {
HandleScope scope; HandleScope scope;
need_tick_cb = true; need_tick_cb = true;
// TODO: this tick_spinner shouldn't be necessary. An ev_prepare should be
// sufficent, the problem is only in the case of the very last "tick" -
// there is nothing left to do in the event loop and libev will exit. The
// ev_prepare callback isn't called before exiting. Thus we start this
// tick_spinner to keep the event loop alive long enough to handle it.
ev_idle_start(EV_DEFAULT_UC_ &tick_spinner); ev_idle_start(EV_DEFAULT_UC_ &tick_spinner);
return Undefined(); return Undefined();
} }
@ -175,10 +181,7 @@ static void Spin(EV_P_ ev_idle *watcher, int revents) {
} }
static void Tick(EV_P_ ev_prepare *watcher, int revents) { static void Tick(void) {
assert(watcher == &next_tick_watcher);
assert(revents == EV_PREPARE);
// Avoid entering a V8 scope. // Avoid entering a V8 scope.
if (!need_tick_cb) return; if (!need_tick_cb) return;
@ -207,6 +210,20 @@ static void Tick(EV_P_ ev_prepare *watcher, int revents) {
} }
static void PrepareTick(EV_P_ ev_prepare *watcher, int revents) {
assert(watcher == &prepare_tick_watcher);
assert(revents == EV_PREPARE);
Tick();
}
static void CheckTick(EV_P_ ev_check *watcher, int revents) {
assert(watcher == &check_tick_watcher);
assert(revents == EV_CHECK);
Tick();
}
static void DoPoll(EV_P_ ev_idle *watcher, int revents) { static void DoPoll(EV_P_ ev_idle *watcher, int revents) {
assert(watcher == &eio_poller); assert(watcher == &eio_poller);
assert(revents == EV_IDLE); assert(revents == EV_IDLE);
@ -1808,8 +1825,12 @@ int main(int argc, char *argv[]) {
ev_default_loop(EVFLAG_AUTO); ev_default_loop(EVFLAG_AUTO);
#endif #endif
ev_prepare_init(&node::next_tick_watcher, node::Tick); ev_prepare_init(&node::prepare_tick_watcher, node::PrepareTick);
ev_prepare_start(EV_DEFAULT_UC_ &node::next_tick_watcher); ev_prepare_start(EV_DEFAULT_UC_ &node::prepare_tick_watcher);
ev_unref(EV_DEFAULT_UC);
ev_check_init(&node::check_tick_watcher, node::CheckTick);
ev_check_start(EV_DEFAULT_UC_ &node::check_tick_watcher);
ev_unref(EV_DEFAULT_UC); ev_unref(EV_DEFAULT_UC);
ev_idle_init(&node::tick_spinner, node::Spin); ev_idle_init(&node::tick_spinner, node::Spin);

8
test/simple/test-next-tick-ordering2.js

@ -3,13 +3,13 @@ assert = common.assert
var order = []; var order = [];
process.nextTick(function () { process.nextTick(function () {
process.nextTick(function() {
order.push('nextTick');
});
setTimeout(function() { setTimeout(function() {
order.push('setTimeout'); order.push('setTimeout');
}, 0); }, 0);
process.nextTick(function() {
order.push('nextTick');
});
}) })
process.addListener('exit', function () { process.addListener('exit', function () {

Loading…
Cancel
Save