diff --git a/src/node.cc b/src/node.cc index 96f131939f..01b9ed5c9e 100644 --- a/src/node.cc +++ b/src/node.cc @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -940,6 +941,7 @@ static Local Load(int argc, char *argv[]) { // Initialize the C++ modules..................filename of module + IdleWatcher::Initialize(process); // idle_watcher.cc Stdio::Initialize(process); // stdio.cc Timer::Initialize(process); // timer.cc SignalHandler::Initialize(process); // signal_handler.cc diff --git a/src/node_constants.cc b/src/node_constants.cc index 216c0e49c3..a28bad4635 100644 --- a/src/node_constants.cc +++ b/src/node_constants.cc @@ -8,11 +8,16 @@ #include #include +#include + namespace node { using namespace v8; void DefineConstants(Handle target) { + NODE_DEFINE_CONSTANT(target, EV_MINPRI); + NODE_DEFINE_CONSTANT(target, EV_MAXPRI); + // file access modes NODE_DEFINE_CONSTANT(target, O_RDONLY); NODE_DEFINE_CONSTANT(target, O_WRONLY); diff --git a/src/node_idle_watcher.cc b/src/node_idle_watcher.cc new file mode 100644 index 0000000000..fc09953e69 --- /dev/null +++ b/src/node_idle_watcher.cc @@ -0,0 +1,118 @@ +// Copyright 2009 Ryan Dahl +#include + +#include +#include + +#include + +namespace node { + +using namespace v8; + +Persistent IdleWatcher::constructor_template; +Persistent callback_symbol; + +void IdleWatcher::Initialize(Handle target) { + HandleScope scope; + + Local t = FunctionTemplate::New(IdleWatcher::New); + constructor_template = Persistent::New(t); + constructor_template->InstanceTemplate()->SetInternalFieldCount(1); + constructor_template->SetClassName(String::NewSymbol("IdleWatcher")); + + NODE_SET_PROTOTYPE_METHOD(constructor_template, "start", IdleWatcher::Start); + NODE_SET_PROTOTYPE_METHOD(constructor_template, "stop", IdleWatcher::Stop); + NODE_SET_PROTOTYPE_METHOD(constructor_template, "setPriority", + IdleWatcher::SetPriority); + + target->Set(String::NewSymbol("IdleWatcher"), constructor_template->GetFunction()); + + callback_symbol = NODE_PSYMBOL("callback"); +} + + +Handle IdleWatcher::SetPriority(const Arguments& args) { + IdleWatcher *idle = ObjectWrap::Unwrap(args.Holder()); + + HandleScope scope; + + int priority = args[0]->Int32Value(); + + ev_set_priority(&idle->watcher_, priority); + + return Undefined(); +} + + +void IdleWatcher::Callback(EV_P_ ev_idle *w, int revents) { + IdleWatcher *idle = static_cast(w->data); + + assert(w == &idle->watcher_); + assert(revents == EV_IDLE); + + HandleScope scope; + + Local callback_v = idle->handle_->Get(callback_symbol); + if (!callback_v->IsFunction()) { + idle->Stop(); + return; + } + + Local callback = Local::Cast(callback_v); + + TryCatch try_catch; + + callback->Call(idle->handle_, 0, NULL); + + if (try_catch.HasCaught()) { + FatalException(try_catch); + } +} + + +// +// var idle = new process.IdleWatcher(); +// idle.callback = function () { /* ... */ }; +// idle.start(); +// +Handle IdleWatcher::New(const Arguments& args) { + HandleScope scope; + + IdleWatcher *s = new IdleWatcher(); + s->Wrap(args.This()); + + return args.This(); +} + + +Handle IdleWatcher::Start(const Arguments& args) { + HandleScope scope; + + IdleWatcher *idle = ObjectWrap::Unwrap(args.Holder()); + + ev_idle_start(EV_DEFAULT_UC_ &idle->watcher_); + + idle->Ref(); + + return Undefined(); +} + + +Handle IdleWatcher::Stop(const Arguments& args) { + HandleScope scope; + IdleWatcher *idle = ObjectWrap::Unwrap(args.Holder()); + idle->Stop(); + return Undefined(); +} + + +void IdleWatcher::Stop () { + if (watcher_.active) { + ev_idle_stop(EV_DEFAULT_UC_ &watcher_); + Unref(); + } +} + + +} // namespace node diff --git a/src/node_idle_watcher.h b/src/node_idle_watcher.h new file mode 100644 index 0000000000..99cbf7601f --- /dev/null +++ b/src/node_idle_watcher.h @@ -0,0 +1,41 @@ +// Copyright 2009 Ryan Dahl +#ifndef NODE_IDLE_H_ +#define NODE_IDLE_H_ + +#include +#include + +namespace node { + +class IdleWatcher : ObjectWrap { + public: + static void Initialize(v8::Handle target); + + protected: + static v8::Persistent constructor_template; + + IdleWatcher() : ObjectWrap() { + ev_idle_init(&watcher_, IdleWatcher::Callback); + watcher_.data = this; + } + + ~IdleWatcher() { + ev_idle_stop(EV_DEFAULT_UC_ &watcher_); + } + + static v8::Handle New(const v8::Arguments& args); + static v8::Handle Start(const v8::Arguments& args); + static v8::Handle Stop(const v8::Arguments& args); + static v8::Handle SetPriority(const v8::Arguments& args); + + private: + static void Callback(EV_P_ ev_idle *watcher, int revents); + + void Stop(); + + ev_idle watcher_; +}; + +} // namespace node +#endif // NODE_IDLE_H_ + diff --git a/test/mjsunit/test-idle-watcher.js b/test/mjsunit/test-idle-watcher.js new file mode 100644 index 0000000000..cd037fb442 --- /dev/null +++ b/test/mjsunit/test-idle-watcher.js @@ -0,0 +1,14 @@ +process.mixin(require("./common")); + +var complete = false; +var idle = new process.IdleWatcher(); +idle.callback = function () { + complete = true; + idle.stop(); +}; +idle.setPriority(process.EVMAXPRI); +idle.start(); + +process.addListener('exit', function () { + assert.ok(complete); +}); diff --git a/wscript b/wscript index 6b822dc700..e6275e58a5 100644 --- a/wscript +++ b/wscript @@ -338,6 +338,7 @@ def build(bld): src/node_stat.cc src/node_stdio.cc src/node_timer.cc + src/node_idle_watcher.cc """ node.includes = """ src/