Timers on Events
This commit is contained in:
Родитель
2ecd7ffe54
Коммит
b4af3b9fb5
23
src/node.js
23
src/node.js
|
@ -1,20 +1,23 @@
|
|||
node.tcp.Server = function (on_connection, options) {
|
||||
this.__proto__ = node.tcp.LowLevelServer ();
|
||||
node.debug("hello world");
|
||||
if (on_connection) this.addListener("Connection", on_connection);
|
||||
node.tcp.createServer = function (on_connection, options) {
|
||||
var server = new node.tcp.Server();
|
||||
server.addListener("Connection", on_connection);
|
||||
//server.setOptions(options);
|
||||
return server;
|
||||
};
|
||||
|
||||
// Timers
|
||||
|
||||
function setTimeout (callback, delay) {
|
||||
var timer = new node.Timer(callback, delay, 0);
|
||||
timer.start();
|
||||
function setTimeout (callback, after) {
|
||||
var timer = new node.Timer();
|
||||
timer.addListener("Timeout", callback);
|
||||
timer.start(after, 0);
|
||||
return timer;
|
||||
}
|
||||
|
||||
function setInterval (callback, delay) {
|
||||
var timer = new node.Timer(callback, delay, delay);
|
||||
timer.start();
|
||||
function setInterval (callback, repeat) {
|
||||
var timer = new node.Timer();
|
||||
timer.addListener("Timeout", callback);
|
||||
timer.start(repeat, repeat);
|
||||
return timer;
|
||||
}
|
||||
|
||||
|
|
79
src/timer.cc
79
src/timer.cc
|
@ -5,7 +5,7 @@
|
|||
using namespace v8;
|
||||
using namespace node;
|
||||
|
||||
#define CALLBACK_SYMBOL String::NewSymbol("callback")
|
||||
#define REPEAT_SYMBOL String::NewSymbol("repeat")
|
||||
|
||||
Persistent<FunctionTemplate> Timer::constructor_template;
|
||||
|
||||
|
@ -16,31 +16,50 @@ Timer::Initialize (Handle<Object> target)
|
|||
|
||||
Local<FunctionTemplate> t = FunctionTemplate::New(Timer::New);
|
||||
constructor_template = Persistent<FunctionTemplate>::New(t);
|
||||
constructor_template->Inherit(EventEmitter::constructor_template);
|
||||
constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
|
||||
|
||||
NODE_SET_PROTOTYPE_METHOD(constructor_template, "start", Timer::Start);
|
||||
NODE_SET_PROTOTYPE_METHOD(constructor_template, "stop", Timer::Stop);
|
||||
|
||||
constructor_template->PrototypeTemplate()->SetAccessor(REPEAT_SYMBOL,
|
||||
RepeatGetter, RepeatSetter);
|
||||
|
||||
target->Set(String::NewSymbol("Timer"), constructor_template->GetFunction());
|
||||
}
|
||||
|
||||
Handle<Value>
|
||||
Timer::RepeatGetter (Local<String> property, const AccessorInfo& info)
|
||||
{
|
||||
HandleScope scope;
|
||||
Timer *timer = NODE_UNWRAP(Timer, info.This());
|
||||
|
||||
assert(timer);
|
||||
assert (property == REPEAT_SYMBOL);
|
||||
|
||||
Local<Integer> v = Integer::New(timer->watcher_.repeat);
|
||||
|
||||
return scope.Close(v);
|
||||
}
|
||||
|
||||
void
|
||||
Timer::RepeatSetter (Local<String> property, Local<Value> value, const AccessorInfo& info)
|
||||
{
|
||||
HandleScope scope;
|
||||
Timer *timer = NODE_UNWRAP(Timer, info.This());
|
||||
|
||||
assert(timer);
|
||||
assert (property == REPEAT_SYMBOL);
|
||||
|
||||
timer->watcher_.repeat = (double)(property->IntegerValue()) / 1000;
|
||||
}
|
||||
|
||||
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_->GetHiddenValue(CALLBACK_SYMBOL);
|
||||
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())
|
||||
FatalException(try_catch);
|
||||
timer->Emit("Timeout", 0, NULL);
|
||||
|
||||
/* XXX i'm a bit worried if this is the correct test?
|
||||
* it's rather crutial for memory leaks the conditional here test to see
|
||||
|
@ -50,18 +69,6 @@ Timer::OnTimeout (EV_P_ ev_timer *watcher, int revents)
|
|||
timer->Detach();
|
||||
}
|
||||
|
||||
Timer::Timer (Handle<Object> handle, Handle<Function> callback, ev_tstamp after, ev_tstamp repeat)
|
||||
: ObjectWrap(handle)
|
||||
{
|
||||
HandleScope scope;
|
||||
|
||||
handle_->SetHiddenValue(CALLBACK_SYMBOL, callback);
|
||||
|
||||
ev_timer_init(&watcher_, Timer::OnTimeout, after, repeat);
|
||||
watcher_.data = this;
|
||||
|
||||
}
|
||||
|
||||
Timer::~Timer ()
|
||||
{
|
||||
ev_timer_stop (EV_DEFAULT_UC_ &watcher_);
|
||||
|
@ -70,17 +77,9 @@ Timer::~Timer ()
|
|||
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 *t = new Timer(args.Holder(), callback, after, repeat);
|
||||
Timer *t = new Timer(args.Holder());
|
||||
ObjectWrap::InformV8ofAllocation(t);
|
||||
|
||||
return args.This();
|
||||
|
@ -90,8 +89,20 @@ Handle<Value>
|
|||
Timer::Start (const Arguments& args)
|
||||
{
|
||||
Timer *timer = NODE_UNWRAP(Timer, args.Holder());
|
||||
HandleScope scope;
|
||||
|
||||
if (args.Length() != 2)
|
||||
return ThrowException(String::New("Bad arguments"));
|
||||
|
||||
ev_tstamp after = (double)(args[0]->IntegerValue()) / 1000.0;
|
||||
ev_tstamp repeat = (double)(args[1]->IntegerValue()) / 1000.0;
|
||||
|
||||
ev_timer_init(&timer->watcher_, Timer::OnTimeout, after, repeat);
|
||||
timer->watcher_.data = timer;
|
||||
ev_timer_start(EV_DEFAULT_UC_ &timer->watcher_);
|
||||
|
||||
timer->Attach();
|
||||
|
||||
return Undefined();
|
||||
}
|
||||
|
||||
|
|
10
src/timer.h
10
src/timer.h
|
@ -2,12 +2,13 @@
|
|||
#define node_timer_h
|
||||
|
||||
#include "node.h"
|
||||
#include "events.h"
|
||||
#include <v8.h>
|
||||
#include <ev.h>
|
||||
|
||||
namespace node {
|
||||
|
||||
class Timer : ObjectWrap {
|
||||
class Timer : EventEmitter {
|
||||
public:
|
||||
static void Initialize (v8::Handle<v8::Object> target);
|
||||
|
||||
|
@ -16,15 +17,14 @@ class Timer : ObjectWrap {
|
|||
protected:
|
||||
static v8::Persistent<v8::FunctionTemplate> constructor_template;
|
||||
|
||||
Timer(v8::Handle<v8::Object> handle,
|
||||
v8::Handle<v8::Function> callback,
|
||||
ev_tstamp after,
|
||||
ev_tstamp repeat);
|
||||
Timer (v8::Handle<v8::Object> handle) : EventEmitter (handle) { }
|
||||
~Timer();
|
||||
|
||||
static v8::Handle<v8::Value> New (const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Start (const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> Stop (const v8::Arguments& args);
|
||||
static v8::Handle<v8::Value> RepeatGetter (v8::Local<v8::String> property, const v8::AccessorInfo& info);
|
||||
static void RepeatSetter (v8::Local<v8::String> property, v8::Local<v8::Value> value, const v8::AccessorInfo& info);
|
||||
|
||||
private:
|
||||
static void OnTimeout (EV_P_ ev_timer *watcher, int revents);
|
||||
|
|
Загрузка…
Ссылка в новой задаче