#include #include #include using namespace v8; using namespace node; Persistent Timer::constructor_template; static Persistent timeout_symbol; static Persistent repeat_symbol; void Timer::Initialize (Handle target) { HandleScope scope; Local t = FunctionTemplate::New(Timer::New); constructor_template = Persistent::New(t); constructor_template->Inherit(EventEmitter::constructor_template); constructor_template->InstanceTemplate()->SetInternalFieldCount(1); constructor_template->SetClassName(String::NewSymbol("Timer")); timeout_symbol = NODE_PSYMBOL("timeout"); repeat_symbol = NODE_PSYMBOL("repeat"); NODE_SET_PROTOTYPE_METHOD(constructor_template, "start", Timer::Start); NODE_SET_PROTOTYPE_METHOD(constructor_template, "stop", Timer::Stop); constructor_template->InstanceTemplate()->SetAccessor(repeat_symbol, RepeatGetter, RepeatSetter); target->Set(String::NewSymbol("Timer"), constructor_template->GetFunction()); } Handle Timer::RepeatGetter (Local property, const AccessorInfo& info) { HandleScope scope; Timer *timer = ObjectWrap::Unwrap(info.This()); assert(timer); assert (property == repeat_symbol); Local v = Integer::New(timer->watcher_.repeat); return scope.Close(v); } void Timer::RepeatSetter (Local property, Local value, const AccessorInfo& info) { HandleScope scope; Timer *timer = ObjectWrap::Unwrap(info.This()); assert(timer); assert(property == repeat_symbol); timer->watcher_.repeat = NODE_V8_UNIXTIME(value); } void Timer::OnTimeout (EV_P_ ev_timer *watcher, int revents) { Timer *timer = static_cast(watcher->data); assert(revents == EV_TIMEOUT); timer->Emit(timeout_symbol, 0, NULL); if (timer->watcher_.repeat == 0) timer->Unref(); } Timer::~Timer () { ev_timer_stop (EV_DEFAULT_UC_ &watcher_); } Handle Timer::New (const Arguments& args) { HandleScope scope; Timer *t = new Timer(); t->Wrap(args.Holder()); return args.This(); } Handle Timer::Start (const Arguments& args) { Timer *timer = ObjectWrap::Unwrap(args.Holder()); HandleScope scope; if (args.Length() != 2) return ThrowException(String::New("Bad arguments")); ev_tstamp after = NODE_V8_UNIXTIME(args[0]); ev_tstamp repeat = NODE_V8_UNIXTIME(args[1]); ev_timer_init(&timer->watcher_, Timer::OnTimeout, after, repeat); timer->watcher_.data = timer; ev_timer_start(EV_DEFAULT_UC_ &timer->watcher_); timer->Ref(); return Undefined(); } Handle Timer::Stop (const Arguments& args) { Timer *timer = ObjectWrap::Unwrap(args.Holder()); if (ev_is_active(&timer->watcher_)) { ev_timer_stop(EV_DEFAULT_UC_ &timer->watcher_); timer->Unref(); } return Undefined(); }