Browse Source

Refactor setTimeout to be a Timer object.

Timer now uses ObjectWrap. setTimeout, setInterval are now implemented in
javascript.
v0.7.4-release
Ryan 16 years ago
parent
commit
f213a27657
  1. 23
      src/main.js
  2. 4
      src/node.cc
  3. 103
      src/timer.cc
  4. 11
      src/timer.h
  5. 146
      src/timers.cc
  6. 11
      src/timers.h
  7. 2
      wscript

23
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 () {
function findScript(base_directory, name, callback) { function findScript(base_directory, name, callback) {
// in the future this function will be more complicated // in the future this function will be more complicated

4
src/node.cc

@ -4,7 +4,7 @@
#include "file.h" #include "file.h"
#include "process.h" #include "process.h"
#include "http.h" #include "http.h"
#include "timers.h" #include "timer.h"
#include "natives.h" #include "natives.h"
@ -246,7 +246,7 @@ main (int argc, char *argv[])
// BUILT-IN MODULES // BUILT-IN MODULES
node::Init_net(g); node::Init_net(g);
node::Init_timers(g); node::Init_timer(g);
node::Init_process(g); node::Init_process(g);
node::Init_file(g); node::Init_file(g);
node::Init_http(g); node::Init_http(g);

103
src/timer.cc

@ -0,0 +1,103 @@
#include "node.h"
#include "timer.h"
#include <assert.h>
using namespace v8;
class Timer : node::ObjectWrap {
public:
Timer(Handle<Object> handle, Handle<Function> callback, ev_tstamp after, ev_tstamp repeat);
~Timer();
static Handle<Value> New (const Arguments& args);
static Handle<Value> Start (const Arguments& args);
static Handle<Value> 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<Timer*>(watcher->data);
HandleScope scope;
Local<Value> callback_value = timer->handle_->Get(String::NewSymbol("callback"));
if (!callback_value->IsFunction())
return;
Local<Function> callback = Local<Function>::Cast(callback_value);
TryCatch try_catch;
callback->Call (timer->handle_, 0, NULL);
if (try_catch.HasCaught())
node::fatal_exception(try_catch);
}
Timer::Timer (Handle<Object> handle, Handle<Function> 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<Value>
Timer::New (const Arguments& args)
{
if (args.Length() < 2)
return Undefined();
HandleScope scope;
Local<Function> callback = Local<Function>::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<Value>
Timer::Start (const Arguments& args)
{
Timer *timer = NODE_UNWRAP(Timer, args.Holder());
ev_timer_start(EV_DEFAULT_UC_ &timer->watcher_);
return Undefined();
}
Handle<Value>
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<Object> target)
{
HandleScope scope;
Local<FunctionTemplate> 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);
}

11
src/timer.h

@ -0,0 +1,11 @@
#ifndef node_timer_h
#define node_timer_h
#include <v8.h>
namespace node {
void Init_timer (v8::Handle<v8::Object> target);
} // namespace node
#endif // node_timer_h

146
src/timers.cc

@ -1,146 +0,0 @@
#include "node.h"
#include "timers.h"
#include <assert.h>
using namespace v8;
static Persistent<ObjectTemplate> timer_template;
class Timer {
public:
Timer(Handle<Function> callback, ev_tstamp after, ev_tstamp repeat);
~Timer();
static Handle<Value> setTimeout (const Arguments& args);
static Handle<Value> setInterval (const Arguments& args);
static Handle<Value> clearTimeout (const Arguments& args);
Persistent<Object> handle_;
private:
static Timer* Unwrap (Handle<Object> handle);
static void OnTimeout (EV_P_ ev_timer *watcher, int revents);
ev_timer watcher_;
};
Timer*
Timer::Unwrap (Handle<Object> handle)
{
HandleScope scope;
Handle<External> field = Handle<External>::Cast(handle->GetInternalField(0));
Timer* timer = static_cast<Timer*>(field->Value());
return timer;
}
void
Timer::OnTimeout (EV_P_ ev_timer *watcher, int revents)
{
Timer *timer = static_cast<Timer*>(watcher->data);
HandleScope scope;
Local<Value> callback_value = timer->handle_->Get(String::NewSymbol("callback"));
if (!callback_value->IsFunction())
return;
Local<Function> callback = Local<Function>::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<Function> callback, ev_tstamp after, ev_tstamp repeat)
{
HandleScope scope;
handle_ = Persistent<Object>::New(timer_template->NewInstance());
handle_->Set(String::NewSymbol("callback"), callback);
Local<External> 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<Value>
Timer::setTimeout (const Arguments& args)
{
if (args.Length() < 2)
return Undefined();
HandleScope scope;
Local<Function> callback = Local<Function>::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<Value>
Timer::setInterval (const Arguments& args)
{
if (args.Length() < 2)
return Undefined();
HandleScope scope;
Local<Function> callback = Local<Function>::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<Value>
Timer::clearTimeout (const Arguments& args)
{
if (args.Length() < 1)
return Undefined();
HandleScope scope;
Local<Object> handle = Local<Object>::Cast(args[0]);
Timer *timer = Timer::Unwrap(handle);
delete timer;
return Undefined();
}
void
node::Init_timers (Handle<Object> target)
{
HandleScope scope;
timer_template = Persistent<ObjectTemplate>::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);
}

11
src/timers.h

@ -1,11 +0,0 @@
#ifndef node_timers_h
#define node_timers_h
#include <v8.h>
namespace node {
void Init_timers (v8::Handle<v8::Object> target);
} // namespace node
#endif // node_timers_h

2
wscript

@ -160,7 +160,7 @@ def build(bld):
src/net.cc src/net.cc
src/process.cc src/process.cc
src/file.cc src/file.cc
src/timers.cc src/timer.cc
""" """
node.includes = """ node.includes = """
src/ src/

Loading…
Cancel
Save