From f219938b69c0af4a18714fb73ff9a58b3ac831c1 Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Sun, 13 Dec 2009 15:43:58 +0100 Subject: [PATCH] add io watcher --- src/node.cc | 8 ++- src/node_io_watcher.cc | 126 +++++++++++++++++++++++++++++++++++++++++ src/node_io_watcher.h | 40 +++++++++++++ wscript | 1 + 4 files changed, 173 insertions(+), 2 deletions(-) create mode 100644 src/node_io_watcher.cc create mode 100644 src/node_io_watcher.h diff --git a/src/node.cc b/src/node.cc index cb6b94291e..d150e9e5b4 100644 --- a/src/node.cc +++ b/src/node.cc @@ -11,6 +11,7 @@ #include /* dlopen(), dlsym() */ #include +#include #include #include #include @@ -849,10 +850,13 @@ static Local Load(int argc, char *argv[]) { // Initialize the C++ modules..................filename of module InitBuffer(process); // buffer.cc - Stdio::Initialize(process); // stdio.cc + + IOWatcher::Initialize(process); // io_watcher.cc Timer::Initialize(process); // timer.cc - SignalHandler::Initialize(process); // signal_handler.cc Stat::Initialize(process); // stat.cc + SignalHandler::Initialize(process); // signal_handler.cc + + Stdio::Initialize(process); // stdio.cc ChildProcess::Initialize(process); // child_process.cc DefineConstants(process); // constants.cc // Create node.dns diff --git a/src/node_io_watcher.cc b/src/node_io_watcher.cc new file mode 100644 index 0000000000..7017d3ea13 --- /dev/null +++ b/src/node_io_watcher.cc @@ -0,0 +1,126 @@ +// Copyright 2009 Ryan Dahl +#include + +#include + +namespace node { + +using namespace v8; + +Persistent IOWatcher::constructor_template; + +void IOWatcher::Initialize(Handle target) { + HandleScope scope; + + Local t = FunctionTemplate::New(IOWatcher::New); + constructor_template = Persistent::New(t); + constructor_template->InstanceTemplate()->SetInternalFieldCount(2); + constructor_template->SetClassName(String::NewSymbol("IOWatcher")); + + NODE_SET_PROTOTYPE_METHOD(constructor_template, "start", IOWatcher::Start); + NODE_SET_PROTOTYPE_METHOD(constructor_template, "stop", IOWatcher::Stop); + + target->Set(String::NewSymbol("IOWatcher"), constructor_template->GetFunction()); +} + + +void IOWatcher::Callback(EV_P_ ev_io *w, int revents) { + IOWatcher *io = static_cast(w->data); + assert(w == &io->watcher_); + HandleScope scope; + + Local callback_v = io->handle_->GetInternalField(1); + assert(callback_v->IsFunction()); + Local callback = Local::Cast(callback_v); + + TryCatch try_catch; + + Local argv[2]; + argv[0] = Local::New(revents & EV_READ ? True() : False()); + argv[1] = Local::New(revents & EV_WRITE ? True() : False()); + + callback->Call(io->handle_, 2, argv); + + if (try_catch.HasCaught()) { + FatalException(try_catch); + } +} + + +// +// var io = new process.IOWatcher(fd, true, true, function (readable, writable) { +// +// }); +// +Handle IOWatcher::New(const Arguments& args) { + HandleScope scope; + + if (!args[0]->IsInt32()) { + return ThrowException(Exception::TypeError( + String::New("First arg should be a file descriptor."))); + } + + int fd = args[0]->Int32Value(); + + if (!args[1]->IsBoolean()) { + return ThrowException(Exception::TypeError( + String::New("Second arg should boolean (readable)."))); + } + + int events = 0; + + if (args[1]->IsTrue()) events |= EV_READ; + + if (!args[2]->IsBoolean()) { + return ThrowException(Exception::TypeError( + String::New("Third arg should boolean (writable)."))); + } + + if (args[2]->IsTrue()) events |= EV_WRITE; + + if (!args[3]->IsFunction()) { + return ThrowException(Exception::TypeError( + String::New("Fourth arg should a callback."))); + } + + Local callback = Local::Cast(args[3]); + + IOWatcher *s = new IOWatcher(fd, events); + + s->Wrap(args.This()); + s->handle_->SetInternalField(1, callback); + + return args.This(); +} + + +Handle IOWatcher::Start(const Arguments& args) { + HandleScope scope; + + IOWatcher *io = ObjectWrap::Unwrap(args.Holder()); + + ev_io_start(EV_DEFAULT_UC_ &io->watcher_); + + io->Ref(); + + return Undefined(); +} + + +Handle IOWatcher::Stop(const Arguments& args) { + HandleScope scope; + IOWatcher *io = ObjectWrap::Unwrap(args.Holder()); + io->Stop(); + return Undefined(); +} + + +void IOWatcher::Stop () { + if (watcher_.active) { + ev_io_stop(EV_DEFAULT_UC_ &watcher_); + Unref(); + } +} + + +} // namespace node diff --git a/src/node_io_watcher.h b/src/node_io_watcher.h new file mode 100644 index 0000000000..4e40593241 --- /dev/null +++ b/src/node_io_watcher.h @@ -0,0 +1,40 @@ +// Copyright 2009 Ryan Dahl +#ifndef NODE_IO_H_ +#define NODE_IO_H_ + +#include +#include + +namespace node { + +class IOWatcher : ObjectWrap { + public: + static void Initialize(v8::Handle target); + + protected: + static v8::Persistent constructor_template; + + IOWatcher(int fd, int events) : ObjectWrap() { + ev_io_init(&watcher_, IOWatcher::Callback, fd, events); + watcher_.data = this; + } + + ~IOWatcher() { + Stop(); + } + + static v8::Handle New(const v8::Arguments& args); + static v8::Handle Start(const v8::Arguments& args); + static v8::Handle Stop(const v8::Arguments& args); + + private: + static void Callback(EV_P_ ev_io *watcher, int revents); + + void Stop(); + + ev_io watcher_; +}; + +} // namespace node +#endif // NODE_IO_H_ + diff --git a/wscript b/wscript index 1f4c131cd2..773a17fb77 100644 --- a/wscript +++ b/wscript @@ -323,6 +323,7 @@ def build(bld): node.source = """ src/node.cc src/node_buffer.cc + src/node_io_watcher.cc src/node_child_process.cc src/node_constants.cc src/node_dns.cc