diff --git a/src/node.cc b/src/node.cc index c24ecd31dc..408bd86588 100644 --- a/src/node.cc +++ b/src/node.cc @@ -68,6 +68,34 @@ static ev_async eio_want_poll_notifier; static ev_async eio_done_poll_notifier; static ev_idle eio_poller; +static ev_idle gc_idle_watcher; +static ev_timer gc_timer; +#define GC_INTERVAL 1.0 + + +// Node calls this every GC_INTERVAL seconds in order to try +// and turn on the gc_idle_watcher, which will eventually (when the process +// isn't busy) call the GC +static void GCTimeout(EV_P_ ev_timer *watcher, int revents) { + assert(watcher == &gc_timer); + assert(revents == EV_TIMER); + + if (ev_pending_count() == 0 && !ev_is_active(&gc_idle_watcher)) { + ev_idle_start(EV_DEFAULT_UC_ &gc_idle_watcher); + ev_unref(EV_DEFAULT_UC); + } +} + + +static void DoGC(EV_P_ ev_idle *watcher, int revents) { + assert(watcher == &gc_idle_watcher); + assert(revents == EV_IDLE); + if (V8::IdleNotification()) { + ev_ref(EV_DEFAULT_UC); + ev_idle_stop(EV_DEFAULT_UC_ watcher); + } +} + static void DoPoll(EV_P_ ev_idle *watcher, int revents) { assert(watcher == &eio_poller); @@ -1125,6 +1153,17 @@ int main(int argc, char *argv[]) { // Initialize the default ev loop. ev_default_loop(EVFLAG_AUTO); + + // The idle watcher which will call GC + ev_idle_init(&node::gc_idle_watcher, node::DoGC); + ev_set_priority(&node::gc_idle_watcher, EV_MINPRI); + // The check for pending events (will start the idle watcher) + ev_timer_init(&node::gc_timer, node::GCTimeout, GC_INTERVAL, GC_INTERVAL); + ev_set_priority(&node::gc_timer, EV_MINPRI); + ev_timer_start(EV_DEFAULT_UC_ &node::gc_timer); + ev_unref(EV_DEFAULT_UC); + + // Setup the EIO thread pool { // It requires 3, yes 3, watchers. ev_idle_init(&node::eio_poller, node::DoPoll);