Thinner SignalWatcher, only using callback
authorJonas Pfenniger <jonas@pfenniger.name>
Fri, 14 May 2010 07:57:02 +0000 (09:57 +0200)
committerRyan Dahl <ry@tinyclouds.org>
Sat, 15 May 2010 01:57:17 +0000 (18:57 -0700)
Since it is only used internally, we don't need the complexity of
EventEmitter. The new SignalWatcher's design was copied from
IdleWatcher.

src/node.js
src/node_signal_watcher.cc
src/node_signal_watcher.h

index 4a6ed96..0ec16f2 100644 (file)
@@ -74,9 +74,10 @@ process.addListener("newListener", function (event) {
   if (isSignal(event) && process.listeners(event).length === 0) {
     var b = process.binding('signal_watcher');
     var w = new b.SignalWatcher(process[event]);
-    w.addListener("signal", function () {
+    w.callback = function () {
       process.emit(event);
-    });
+    };
+    w.start();
   }
 });
 
index 1eff3ba..c8dd3c7 100644 (file)
@@ -7,38 +7,46 @@ namespace node {
 using namespace v8;
 
 Persistent<FunctionTemplate> SignalWatcher::constructor_template;
-static Persistent<String> signal_symbol;
+static Persistent<String> callback_symbol;
 
 void SignalWatcher::Initialize(Handle<Object> target) {
   HandleScope scope;
 
   Local<FunctionTemplate> t = FunctionTemplate::New(SignalWatcher::New);
   constructor_template = Persistent<FunctionTemplate>::New(t);
-  constructor_template->Inherit(EventEmitter::constructor_template);
   constructor_template->InstanceTemplate()->SetInternalFieldCount(1);
   constructor_template->SetClassName(String::NewSymbol("SignalWatcher"));
 
+  NODE_SET_PROTOTYPE_METHOD(constructor_template, "start", SignalWatcher::Start);
   NODE_SET_PROTOTYPE_METHOD(constructor_template, "stop", SignalWatcher::Stop);
 
-  signal_symbol = NODE_PSYMBOL("signal");
-
   target->Set(String::NewSymbol("SignalWatcher"),
       constructor_template->GetFunction());
+  
+  callback_symbol = NODE_PSYMBOL("callback");
 }
 
-void SignalWatcher::OnSignal(EV_P_ ev_signal *watcher, int revents) {
+void SignalWatcher::Callback(EV_P_ ev_signal *watcher, int revents) {
   SignalWatcher *w = static_cast<SignalWatcher*>(watcher->data);
+
+  assert(watcher == &w->watcher_);
+
   HandleScope scope;
 
-  assert(revents == EV_SIGNAL);
+  Local<Value> callback_v = w->handle_->Get(callback_symbol);
+  if (!callback_v->IsFunction()) {
+    w->Stop();
+    return;
+  }
 
-  w->Emit(signal_symbol, 0, NULL);
-}
+  Local<Function> callback = Local<Function>::Cast(callback_v);
 
-SignalWatcher::~SignalWatcher() {
-  if (watcher_.active) {
-    ev_ref(EV_DEFAULT_UC);
-    ev_signal_stop(EV_DEFAULT_UC_ &watcher_);
+  TryCatch try_catch;
+
+  callback->Call(w->handle_, 0, NULL);
+
+  if (try_catch.HasCaught()) {
+    FatalException(try_catch);
   }
 }
 
@@ -51,30 +59,40 @@ Handle<Value> SignalWatcher::New(const Arguments& args) {
 
   int sig = args[0]->Int32Value();
 
-  SignalWatcher *w = new SignalWatcher();
+  SignalWatcher *w = new SignalWatcher(sig);
   w->Wrap(args.Holder());
 
-  ev_signal_init(&w->watcher_, SignalWatcher::OnSignal, sig);
-  w->watcher_.data = w;
-  // Give signal handlers very high priority. The only thing that has higher
-  // priority is the garbage collector check.
-  ev_set_priority(&w->watcher_, EV_MAXPRI-1);
-  ev_signal_start(EV_DEFAULT_UC_ &w->watcher_);
-  ev_unref(EV_DEFAULT_UC);
+  return args.This();
+}
 
-  w->Ref();
+Handle<Value> SignalWatcher::Start(const Arguments& args) {
+  HandleScope scope;
+  SignalWatcher *w = ObjectWrap::Unwrap<SignalWatcher>(args.Holder());
+  w->Start();
+  return Undefined();
+}
 
-  return args.This();
+void SignalWatcher::Start () {
+  if (!watcher_.active) {
+    ev_signal_start(EV_DEFAULT_UC_ &watcher_);
+    ev_unref(EV_DEFAULT_UC);
+    Ref();
+  }
 }
 
 Handle<Value> SignalWatcher::Stop(const Arguments& args) {
   HandleScope scope;
-
   SignalWatcher *w = ObjectWrap::Unwrap<SignalWatcher>(args.Holder());
-  ev_ref(EV_DEFAULT_UC);
-  ev_signal_stop(EV_DEFAULT_UC_ &w->watcher_);
-  w->Unref();
+  w->Stop();
   return Undefined();
 }
 
+void SignalWatcher::Stop () {
+  if (watcher_.active) {
+    ev_ref(EV_DEFAULT_UC);
+    ev_signal_stop(EV_DEFAULT_UC_ &watcher_);
+    Unref();
+  }
+}
+
 }  // namespace node
index dc66e96..a875dd1 100644 (file)
 
 namespace node {
 
-class SignalWatcher : EventEmitter {
+class SignalWatcher : ObjectWrap {
  public:
   static void Initialize(v8::Handle<v8::Object> target);
 
  protected:
   static v8::Persistent<v8::FunctionTemplate> constructor_template;
 
-  SignalWatcher() : EventEmitter() { }
-  ~SignalWatcher();
+  SignalWatcher(int sig) : ObjectWrap() {
+    ev_signal_init(&watcher_, SignalWatcher::Callback, sig);
+    watcher_.data = this;
+  }
+  
+  ~SignalWatcher() {
+    ev_signal_stop(EV_DEFAULT_UC_ &watcher_);
+  }
 
   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);
 
  private:
-  static void OnSignal(EV_P_ ev_signal *watcher, int revents);
+  static void Callback(EV_P_ ev_signal *watcher, int revents);
+  
+  void Start();
+  void Stop();
+  
   ev_signal watcher_;
 };