diff --git a/atom.gyp b/atom.gyp index 11621c57c663..2a1c6e173bb7 100644 --- a/atom.gyp +++ b/atom.gyp @@ -43,6 +43,7 @@ 'browser/native_window_observer.h', 'common/api/api_messages.cc', 'common/api/api_messages.h', + 'common/api/atom_api_idle_gc.cc', 'common/api/atom_api_v8_util.cc', 'common/api/atom_bindings.cc', 'common/api/atom_bindings.h', diff --git a/browser/atom/atom.coffee b/browser/atom/atom.coffee index eb20dbeafa6e..d6ad0bbd3f9f 100644 --- a/browser/atom/atom.coffee +++ b/browser/atom/atom.coffee @@ -1,6 +1,9 @@ fs = require 'fs' path = require 'path' +# Enable idle gc. +process.atom_binding('idle_gc').start() + # Provide default Content API implementations. atom = {} diff --git a/common/api/atom_api_idle_gc.cc b/common/api/atom_api_idle_gc.cc new file mode 100644 index 000000000000..5756979341a0 --- /dev/null +++ b/common/api/atom_api_idle_gc.cc @@ -0,0 +1,80 @@ +// Copyright (c) 2013 GitHub, Inc. All rights reserved. +// Copyright (c) 2012, Ben Noordhuis . +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "vendor/node/src/node.h" + +namespace { + +using v8::Arguments; +using v8::FunctionTemplate; +using v8::Handle; +using v8::HandleScope; +using v8::Object; +using v8::String; +using v8::Undefined; +using v8::V8; +using v8::Value; + +typedef enum { STOP, RUN, PAUSE } gc_state_t; + +int64_t interval; +gc_state_t state; +gc_state_t prev_state; +uv_timer_t timer_handle; +uv_check_t check_handle; +uv_prepare_t prepare_handle; + +void Timer(uv_timer_t*, int) { + if (V8::IdleNotification()) state = PAUSE; +} + +void Check(uv_check_t*, int) { + prev_state = state; +} + +void Prepare(uv_prepare_t*, int) { + if (state == PAUSE && prev_state == PAUSE) state = RUN; + if (state == RUN) uv_timer_start(&timer_handle, Timer, interval, 0); +} + +Handle Stop(const Arguments& args) { + state = STOP; + uv_timer_stop(&timer_handle); + uv_check_stop(&check_handle); + uv_prepare_stop(&prepare_handle); + return Undefined(); +} + +Handle Start(const Arguments& args) { + HandleScope scope; + Stop(args); + + interval = args[0]->IsNumber() ? args[0]->IntegerValue() : 0; + if (interval <= 0) interval = 5000; // Default to 5 seconds. + + state = RUN; + uv_check_start(&check_handle, Check); + uv_prepare_start(&prepare_handle, Prepare); + + return Undefined(); +} + +void Init(Handle obj) { + HandleScope scope; + + uv_timer_init(uv_default_loop(), &timer_handle); + uv_check_init(uv_default_loop(), &check_handle); + uv_prepare_init(uv_default_loop(), &prepare_handle); + uv_unref(reinterpret_cast(&timer_handle)); + uv_unref(reinterpret_cast(&check_handle)); + uv_unref(reinterpret_cast(&prepare_handle)); + + obj->Set(String::New("stop"), FunctionTemplate::New(Stop)->GetFunction()); + obj->Set(String::New("start"), FunctionTemplate::New(Start)->GetFunction()); +} + +NODE_MODULE(atom_common_idle_gc, Init) + +} // namespace diff --git a/common/api/atom_extensions.h b/common/api/atom_extensions.h index 879ccae7b4d4..6e75609609b3 100644 --- a/common/api/atom_extensions.h +++ b/common/api/atom_extensions.h @@ -18,6 +18,7 @@ NODE_EXT_LIST_ITEM(atom_renderer_ipc) // Module names start with `atom_common_` can be used by both browser and // renderer processes. +NODE_EXT_LIST_ITEM(atom_common_idle_gc) NODE_EXT_LIST_ITEM(atom_common_v8_util) NODE_EXT_LIST_END