diff --git a/src/main.js b/src/main.js index 59298406c4..6d4fdca1e3 100644 --- a/src/main.js +++ b/src/main.js @@ -32,7 +32,28 @@ node.path = new function () { }; }; -// Namespace for module loading functionality +// Timers + +function setTimeout (callback, delay) { + var timer = new Timer(callback, delay, 0); + timer.start(); + return timer; +}; + +function setInterval (callback, delay) { + var timer = new Timer(callback, delay, delay); + timer.start(); + return timer; +}; + +function clearTimeout (timer) { + timer.stop(); + delete timer; +}; +clearInterval = clearTimeout; + +// Modules + (function () { function findScript(base_directory, name, callback) { // in the future this function will be more complicated diff --git a/src/node.cc b/src/node.cc index 49fb08227e..567691366f 100644 --- a/src/node.cc +++ b/src/node.cc @@ -4,7 +4,7 @@ #include "file.h" #include "process.h" #include "http.h" -#include "timers.h" +#include "timer.h" #include "natives.h" @@ -246,7 +246,7 @@ main (int argc, char *argv[]) // BUILT-IN MODULES node::Init_net(g); - node::Init_timers(g); + node::Init_timer(g); node::Init_process(g); node::Init_file(g); node::Init_http(g); diff --git a/src/timer.cc b/src/timer.cc new file mode 100644 index 0000000000..1d6c504733 --- /dev/null +++ b/src/timer.cc @@ -0,0 +1,103 @@ +#include "node.h" +#include "timer.h" +#include + +using namespace v8; + +class Timer : node::ObjectWrap { + public: + Timer(Handle handle, Handle callback, ev_tstamp after, ev_tstamp repeat); + ~Timer(); + + static Handle New (const Arguments& args); + static Handle Start (const Arguments& args); + static Handle Stop (const Arguments& args); + + private: + static void OnTimeout (EV_P_ ev_timer *watcher, int revents); + ev_timer watcher_; +}; + +void +Timer::OnTimeout (EV_P_ ev_timer *watcher, int revents) +{ + Timer *timer = static_cast(watcher->data); + + HandleScope scope; + + Local callback_value = timer->handle_->Get(String::NewSymbol("callback")); + if (!callback_value->IsFunction()) + return; + + Local callback = Local::Cast(callback_value); + + TryCatch try_catch; + callback->Call (timer->handle_, 0, NULL); + if (try_catch.HasCaught()) + node::fatal_exception(try_catch); +} + +Timer::Timer (Handle handle, Handle callback, ev_tstamp after, ev_tstamp repeat) + : ObjectWrap(handle) +{ + HandleScope scope; + + handle_->Set(String::NewSymbol("callback"), callback); + + ev_timer_init(&watcher_, Timer::OnTimeout, after, repeat); + watcher_.data = this; + + ev_timer_start(EV_DEFAULT_UC_ &watcher_); +} + +Timer::~Timer () +{ + ev_timer_stop (EV_DEFAULT_UC_ &watcher_); +} + +Handle +Timer::New (const Arguments& args) +{ + if (args.Length() < 2) + return Undefined(); + + HandleScope scope; + + Local callback = Local::Cast(args[0]); + + ev_tstamp after = (double)(args[1]->IntegerValue()) / 1000.0; + ev_tstamp repeat = (double)(args[2]->IntegerValue()) / 1000.0; + + Timer *timer = new Timer(args.Holder(), callback, after, repeat); + + return scope.Close(timer->handle_); +} + +Handle +Timer::Start (const Arguments& args) +{ + Timer *timer = NODE_UNWRAP(Timer, args.Holder()); + ev_timer_start(EV_DEFAULT_UC_ &timer->watcher_); + return Undefined(); +} + +Handle +Timer::Stop (const Arguments& args) +{ + Timer *timer = NODE_UNWRAP(Timer, args.Holder()); + ev_timer_stop(EV_DEFAULT_UC_ &timer->watcher_); + return Undefined(); +} + +void +node::Init_timer (Handle target) +{ + HandleScope scope; + + Local timer_template = FunctionTemplate::New(Timer::New); + timer_template->InstanceTemplate()->SetInternalFieldCount(1); + target->Set(String::NewSymbol("Timer"), timer_template->GetFunction()); + + NODE_SET_METHOD(timer_template->InstanceTemplate(), "start", Timer::Start); + NODE_SET_METHOD(timer_template->InstanceTemplate(), "stop", Timer::Stop); +} diff --git a/src/timer.h b/src/timer.h new file mode 100644 index 0000000000..ab64c27ae2 --- /dev/null +++ b/src/timer.h @@ -0,0 +1,11 @@ +#ifndef node_timer_h +#define node_timer_h + +#include + +namespace node { + +void Init_timer (v8::Handle target); + +} // namespace node +#endif // node_timer_h diff --git a/src/timers.cc b/src/timers.cc deleted file mode 100644 index 7e23662c1d..0000000000 --- a/src/timers.cc +++ /dev/null @@ -1,146 +0,0 @@ -#include "node.h" -#include "timers.h" -#include - -using namespace v8; - -static Persistent timer_template; - -class Timer { - public: - Timer(Handle callback, ev_tstamp after, ev_tstamp repeat); - ~Timer(); - - static Handle setTimeout (const Arguments& args); - static Handle setInterval (const Arguments& args); - static Handle clearTimeout (const Arguments& args); - - Persistent handle_; - - private: - static Timer* Unwrap (Handle handle); - static void OnTimeout (EV_P_ ev_timer *watcher, int revents); - ev_timer watcher_; -}; - -Timer* -Timer::Unwrap (Handle handle) -{ - HandleScope scope; - Handle field = Handle::Cast(handle->GetInternalField(0)); - Timer* timer = static_cast(field->Value()); - return timer; -} - -void -Timer::OnTimeout (EV_P_ ev_timer *watcher, int revents) -{ - Timer *timer = static_cast(watcher->data); - - HandleScope scope; - - Local callback_value = timer->handle_->Get(String::NewSymbol("callback")); - if (!callback_value->IsFunction()) - return; - - Local callback = Local::Cast(callback_value); - - TryCatch try_catch; - callback->Call (Context::GetCurrent()->Global(), 0, NULL); - if(try_catch.HasCaught()) - node::fatal_exception(try_catch); - - // use ev_is_active instead? - if(watcher->repeat == 0.) - delete timer; -} - -Timer::Timer (Handle callback, ev_tstamp after, ev_tstamp repeat) -{ - HandleScope scope; - - handle_ = Persistent::New(timer_template->NewInstance()); - handle_->Set(String::NewSymbol("callback"), callback); - - Local external = External::New(this); - handle_->SetInternalField(0, external); - - ev_timer_init(&watcher_, Timer::OnTimeout, after, repeat); - watcher_.data = this; - - ev_timer_start(EV_DEFAULT_UC_ &watcher_); -} - -Timer::~Timer () -{ - ev_timer_stop (EV_DEFAULT_UC_ &watcher_); - handle_->SetInternalField(0, Undefined()); - handle_.Dispose(); -} - -Handle -Timer::setTimeout (const Arguments& args) -{ - if (args.Length() < 2) - return Undefined(); - - HandleScope scope; - - Local callback = Local::Cast(args[0]); - int delay = args[1]->IntegerValue(); - - ev_tstamp after = (double)delay / 1000.0; - - if (args.Length() > 2) - assert(0 && "extra params to setTimeout not yet implemented."); - - Timer *timer = new Timer(callback, after, 0.0); - - return scope.Close(timer->handle_); -} - -Handle -Timer::setInterval (const Arguments& args) -{ - if (args.Length() < 2) - return Undefined(); - - HandleScope scope; - - Local callback = Local::Cast(args[0]); - int delay = args[1]->IntegerValue(); - - ev_tstamp after = (double)delay / 1000.0; - - Timer *timer = new Timer(callback, after, after); - - return scope.Close(timer->handle_); -} - -Handle -Timer::clearTimeout (const Arguments& args) -{ - if (args.Length() < 1) - return Undefined(); - - HandleScope scope; - Local handle = Local::Cast(args[0]); - Timer *timer = Timer::Unwrap(handle); - delete timer; - - return Undefined(); -} - -void -node::Init_timers (Handle target) -{ - HandleScope scope; - - timer_template = Persistent::New(ObjectTemplate::New()); - timer_template->SetInternalFieldCount(1); - - NODE_SET_METHOD(target, "setTimeout", Timer::setTimeout); - NODE_SET_METHOD(target, "setInterval", Timer::setInterval); - NODE_SET_METHOD(target, "clearTimeout", Timer::clearTimeout); - NODE_SET_METHOD(target, "clearInterval", Timer::clearTimeout); -} diff --git a/src/timers.h b/src/timers.h deleted file mode 100644 index c63e05af45..0000000000 --- a/src/timers.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef node_timers_h -#define node_timers_h - -#include - -namespace node { - -void Init_timers (v8::Handle target); - -} // namespace node -#endif // node_timers_h diff --git a/wscript b/wscript index afbd3db2da..643b716acc 100644 --- a/wscript +++ b/wscript @@ -160,7 +160,7 @@ def build(bld): src/net.cc src/process.cc src/file.cc - src/timers.cc + src/timer.cc """ node.includes = """ src/