diff options
author | Ryan Dahl <ry@tinyclouds.org> | 2011-07-30 02:22:21 +0400 |
---|---|---|
committer | Ryan Dahl <ry@tinyclouds.org> | 2011-07-30 05:03:44 +0400 |
commit | f01b241057567818160f8cd4f58cf9cafdccf1ed (patch) | |
tree | 8a0eafc1e67504c5a3c77957eccc54cb4438d6a4 /src/pipe_wrap.cc | |
parent | 874260b40fefc03aec7638a736b004b3ca0c23f3 (diff) |
add wrapper for uv_spawn
process.binding('process_wrap')
Diffstat (limited to 'src/pipe_wrap.cc')
-rw-r--r-- | src/pipe_wrap.cc | 250 |
1 files changed, 131 insertions, 119 deletions
diff --git a/src/pipe_wrap.cc b/src/pipe_wrap.cc index eb7069050f8..e6faf55da22 100644 --- a/src/pipe_wrap.cc +++ b/src/pipe_wrap.cc @@ -3,6 +3,7 @@ #include <req_wrap.h> #include <handle_wrap.h> #include <stream_wrap.h> +#include <pipe_wrap.h> #define UNWRAP \ assert(!args.Holder().IsEmpty()); \ @@ -37,176 +38,187 @@ Persistent<Function> pipeConstructor; typedef class ReqWrap<uv_connect_t> ConnectWrap; -class PipeWrap : StreamWrap { - public: +uv_pipe_t* PipeWrap::UVHandle() { + return &handle_; +} - static void Initialize(Handle<Object> target) { - StreamWrap::Initialize(target); - HandleScope scope; +PipeWrap* PipeWrap::Unwrap(Local<Object> obj) { + assert(!obj.IsEmpty()); + assert(obj->InternalFieldCount() > 0); + return static_cast<PipeWrap*>(obj->GetPointerFromInternalField(0)); +} - Local<FunctionTemplate> t = FunctionTemplate::New(New); - t->SetClassName(String::NewSymbol("Pipe")); - t->InstanceTemplate()->SetInternalFieldCount(1); +void PipeWrap::Initialize(Handle<Object> target) { + StreamWrap::Initialize(target); - NODE_SET_PROTOTYPE_METHOD(t, "close", HandleWrap::Close); + HandleScope scope; - NODE_SET_PROTOTYPE_METHOD(t, "readStart", StreamWrap::ReadStart); - NODE_SET_PROTOTYPE_METHOD(t, "readStop", StreamWrap::ReadStop); - NODE_SET_PROTOTYPE_METHOD(t, "write", StreamWrap::Write); - NODE_SET_PROTOTYPE_METHOD(t, "shutdown", StreamWrap::Shutdown); + Local<FunctionTemplate> t = FunctionTemplate::New(New); + t->SetClassName(String::NewSymbol("Pipe")); - NODE_SET_PROTOTYPE_METHOD(t, "bind", Bind); - NODE_SET_PROTOTYPE_METHOD(t, "listen", Listen); - NODE_SET_PROTOTYPE_METHOD(t, "connect", Connect); + t->InstanceTemplate()->SetInternalFieldCount(1); - pipeConstructor = Persistent<Function>::New(t->GetFunction()); + NODE_SET_PROTOTYPE_METHOD(t, "close", HandleWrap::Close); - target->Set(String::NewSymbol("Pipe"), pipeConstructor); - } + NODE_SET_PROTOTYPE_METHOD(t, "readStart", StreamWrap::ReadStart); + NODE_SET_PROTOTYPE_METHOD(t, "readStop", StreamWrap::ReadStop); + NODE_SET_PROTOTYPE_METHOD(t, "write", StreamWrap::Write); + NODE_SET_PROTOTYPE_METHOD(t, "shutdown", StreamWrap::Shutdown); - private: - static Handle<Value> New(const Arguments& args) { - // This constructor should not be exposed to public javascript. - // Therefore we assert that we are not trying to call this as a - // normal function. - assert(args.IsConstructCall()); + NODE_SET_PROTOTYPE_METHOD(t, "bind", Bind); + NODE_SET_PROTOTYPE_METHOD(t, "listen", Listen); + NODE_SET_PROTOTYPE_METHOD(t, "connect", Connect); - HandleScope scope; - PipeWrap* wrap = new PipeWrap(args.This()); - assert(wrap); + pipeConstructor = Persistent<Function>::New(t->GetFunction()); - return scope.Close(args.This()); - } + target->Set(String::NewSymbol("Pipe"), pipeConstructor); +} - PipeWrap(Handle<Object> object) : StreamWrap(object, - (uv_stream_t*) &handle_) { - int r = uv_pipe_init(&handle_); - assert(r == 0); // How do we proxy this error up to javascript? - // Suggestion: uv_pipe_init() returns void. - handle_.data = reinterpret_cast<void*>(this); - UpdateWriteQueueSize(); - } - static Handle<Value> Bind(const Arguments& args) { - HandleScope scope; +Handle<Value> PipeWrap::New(const Arguments& args) { + // This constructor should not be exposed to public javascript. + // Therefore we assert that we are not trying to call this as a + // normal function. + assert(args.IsConstructCall()); - UNWRAP + HandleScope scope; + PipeWrap* wrap = new PipeWrap(args.This()); + assert(wrap); - String::AsciiValue name(args[0]->ToString()); + return scope.Close(args.This()); +} - int r = uv_pipe_bind(&wrap->handle_, *name); - // Error starting the pipe. - if (r) SetErrno(uv_last_error().code); +PipeWrap::PipeWrap(Handle<Object> object) : StreamWrap(object, + (uv_stream_t*) &handle_) { + int r = uv_pipe_init(&handle_); + assert(r == 0); // How do we proxy this error up to javascript? + // Suggestion: uv_pipe_init() returns void. + handle_.data = reinterpret_cast<void*>(this); + UpdateWriteQueueSize(); +} - return scope.Close(Integer::New(r)); - } - static Handle<Value> Listen(const Arguments& args) { - HandleScope scope; +Handle<Value> PipeWrap::Bind(const Arguments& args) { + HandleScope scope; - UNWRAP + UNWRAP - int backlog = args[0]->Int32Value(); + String::AsciiValue name(args[0]->ToString()); - int r = uv_listen((uv_stream_t*)&wrap->handle_, backlog, OnConnection); + int r = uv_pipe_bind(&wrap->handle_, *name); - // Error starting the pipe. - if (r) SetErrno(uv_last_error().code); + // Error starting the pipe. + if (r) SetErrno(uv_last_error().code); - return scope.Close(Integer::New(r)); - } + return scope.Close(Integer::New(r)); +} - // TODO maybe share with TCPWrap? - static void OnConnection(uv_stream_t* handle, int status) { - HandleScope scope; - PipeWrap* wrap = static_cast<PipeWrap*>(handle->data); - assert(&wrap->handle_ == (uv_pipe_t*)handle); +Handle<Value> PipeWrap::Listen(const Arguments& args) { + HandleScope scope; - // We should not be getting this callback if someone as already called - // uv_close() on the handle. - assert(wrap->object_.IsEmpty() == false); + UNWRAP - if (status != 0) { - // TODO Handle server error (set errno and call onconnection with NULL) - assert(0); - return; - } + int backlog = args[0]->Int32Value(); - // Instanciate the client javascript object and handle. - Local<Object> client_obj = pipeConstructor->NewInstance(); + int r = uv_listen((uv_stream_t*)&wrap->handle_, backlog, OnConnection); - // Unwrap the client javascript object. - assert(client_obj->InternalFieldCount() > 0); - PipeWrap* client_wrap = - static_cast<PipeWrap*>(client_obj->GetPointerFromInternalField(0)); + // Error starting the pipe. + if (r) SetErrno(uv_last_error().code); - int r = uv_accept(handle, (uv_stream_t*)&client_wrap->handle_); + return scope.Close(Integer::New(r)); +} - // uv_accept should always work. - assert(r == 0); - // Successful accept. Call the onconnection callback in JavaScript land. - Local<Value> argv[1] = { client_obj }; - MakeCallback(wrap->object_, "onconnection", 1, argv); +// TODO maybe share with TCPWrap? +void PipeWrap::OnConnection(uv_stream_t* handle, int status) { + HandleScope scope; + + PipeWrap* wrap = static_cast<PipeWrap*>(handle->data); + assert(&wrap->handle_ == (uv_pipe_t*)handle); + + // We should not be getting this callback if someone as already called + // uv_close() on the handle. + assert(wrap->object_.IsEmpty() == false); + + if (status != 0) { + // TODO Handle server error (set errno and call onconnection with NULL) + assert(0); + return; } - // TODO Maybe share this with TCPWrap? - static void AfterConnect(uv_connect_t* req, int status) { - ConnectWrap* req_wrap = (ConnectWrap*) req->data; - PipeWrap* wrap = (PipeWrap*) req->handle->data; + // Instanciate the client javascript object and handle. + Local<Object> client_obj = pipeConstructor->NewInstance(); - HandleScope scope; + // Unwrap the client javascript object. + assert(client_obj->InternalFieldCount() > 0); + PipeWrap* client_wrap = + static_cast<PipeWrap*>(client_obj->GetPointerFromInternalField(0)); - // The wrap and request objects should still be there. - assert(req_wrap->object_.IsEmpty() == false); - assert(wrap->object_.IsEmpty() == false); + int r = uv_accept(handle, (uv_stream_t*)&client_wrap->handle_); - if (status) { - SetErrno(uv_last_error().code); - } + // uv_accept should always work. + assert(r == 0); - Local<Value> argv[3] = { - Integer::New(status), - Local<Value>::New(wrap->object_), - Local<Value>::New(req_wrap->object_) - }; + // Successful accept. Call the onconnection callback in JavaScript land. + Local<Value> argv[1] = { client_obj }; + MakeCallback(wrap->object_, "onconnection", 1, argv); +} - MakeCallback(req_wrap->object_, "oncomplete", 3, argv); +// TODO Maybe share this with TCPWrap? +void PipeWrap::AfterConnect(uv_connect_t* req, int status) { + ConnectWrap* req_wrap = (ConnectWrap*) req->data; + PipeWrap* wrap = (PipeWrap*) req->handle->data; - delete req_wrap; + HandleScope scope; + + // The wrap and request objects should still be there. + assert(req_wrap->object_.IsEmpty() == false); + assert(wrap->object_.IsEmpty() == false); + + if (status) { + SetErrno(uv_last_error().code); } - static Handle<Value> Connect(const Arguments& args) { - HandleScope scope; + Local<Value> argv[3] = { + Integer::New(status), + Local<Value>::New(wrap->object_), + Local<Value>::New(req_wrap->object_) + }; - UNWRAP + MakeCallback(req_wrap->object_, "oncomplete", 3, argv); - String::AsciiValue name(args[0]->ToString()); + delete req_wrap; +} - ConnectWrap* req_wrap = new ConnectWrap(); - int r = uv_pipe_connect(&req_wrap->req_, - &wrap->handle_, - *name, - AfterConnect); +Handle<Value> PipeWrap::Connect(const Arguments& args) { + HandleScope scope; - req_wrap->Dispatched(); + UNWRAP - if (r) { - SetErrno(uv_last_error().code); - delete req_wrap; - return scope.Close(v8::Null()); - } else { - return scope.Close(req_wrap->object_); - } - } + String::AsciiValue name(args[0]->ToString()); + + ConnectWrap* req_wrap = new ConnectWrap(); - uv_pipe_t handle_; -}; + int r = uv_pipe_connect(&req_wrap->req_, + &wrap->handle_, + *name, + AfterConnect); + + req_wrap->Dispatched(); + + if (r) { + SetErrno(uv_last_error().code); + delete req_wrap; + return scope.Close(v8::Null()); + } else { + return scope.Close(req_wrap->object_); + } +} } // namespace node |