diff options
author | Ryan Dahl <ry@tinyclouds.org> | 2011-07-18 04:22:16 -0700 |
---|---|---|
committer | Ryan Dahl <ry@tinyclouds.org> | 2011-07-18 04:22:16 -0700 |
commit | 0c7bf8132eed630c81fc96178091d1fc7ad8e65e (patch) | |
tree | 536b4e9c8a345ede05dec6ea9dfba702f7b0b9f1 | |
parent | cc0f608c7c24e52fe8e6a13f72e20ad520dcd5b4 (diff) | |
download | node-0c7bf8132eed630c81fc96178091d1fc7ad8e65e.tar.gz |
Abstract out HandleWrap class
-rw-r--r-- | src/handle_wrap.cc | 89 | ||||
-rw-r--r-- | src/handle_wrap.h | 30 | ||||
-rw-r--r-- | src/stream_wrap.cc | 59 | ||||
-rw-r--r-- | src/stream_wrap.h | 13 | ||||
-rw-r--r-- | src/tcp_wrap.cc | 7 | ||||
-rw-r--r-- | src/timer_wrap.cc | 45 | ||||
-rw-r--r-- | wscript | 1 |
7 files changed, 149 insertions, 95 deletions
diff --git a/src/handle_wrap.cc b/src/handle_wrap.cc new file mode 100644 index 000000000..c34c1c2e6 --- /dev/null +++ b/src/handle_wrap.cc @@ -0,0 +1,89 @@ +#include <node.h> +#include <handle_wrap.h> + +namespace node { + +using v8::Object; +using v8::Handle; +using v8::Local; +using v8::Persistent; +using v8::Value; +using v8::HandleScope; +using v8::FunctionTemplate; +using v8::String; +using v8::Function; +using v8::TryCatch; +using v8::Context; +using v8::Arguments; +using v8::Integer; + + +#define UNWRAP \ + assert(!args.Holder().IsEmpty()); \ + assert(args.Holder()->InternalFieldCount() > 0); \ + HandleWrap* wrap = \ + static_cast<HandleWrap*>(args.Holder()->GetPointerFromInternalField(0)); \ + if (!wrap) { \ + SetErrno(UV_EBADF); \ + return scope.Close(Integer::New(-1)); \ + } + + +void HandleWrap::Initialize(Handle<Object> target) { + /* Doesn't do anything at the moment. */ +} + + +Handle<Value> HandleWrap::Close(const Arguments& args) { + HandleScope scope; + + UNWRAP + + assert(!wrap->object_.IsEmpty()); + int r = uv_close(wrap->handle__, OnClose); + + wrap->StateChange(); + + if (r) { + SetErrno(uv_last_error().code); + + wrap->object_->SetPointerInInternalField(0, NULL); + wrap->object_.Dispose(); + wrap->object_.Clear(); + } + return scope.Close(Integer::New(r)); +} + + +HandleWrap::HandleWrap(Handle<Object> object, uv_handle_t* h) { + handle__ = h; + h->data = this; + + HandleScope scope; + assert(object_.IsEmpty()); + assert(object->InternalFieldCount() > 0); + object_ = v8::Persistent<v8::Object>::New(object); + object_->SetPointerInInternalField(0, this); +} + + +HandleWrap::~HandleWrap() { + assert(object_.IsEmpty()); +} + + +void HandleWrap::OnClose(uv_handle_t* handle) { + HandleWrap* wrap = static_cast<HandleWrap*>(handle->data); + + // The wrap object should still be there. + assert(wrap->object_.IsEmpty() == false); + + wrap->object_->SetPointerInInternalField(0, NULL); + wrap->object_.Dispose(); + wrap->object_.Clear(); + + delete wrap; +} + + +} // namespace node diff --git a/src/handle_wrap.h b/src/handle_wrap.h new file mode 100644 index 000000000..2c51799a5 --- /dev/null +++ b/src/handle_wrap.h @@ -0,0 +1,30 @@ +#ifndef HANDLE_WRAP_H_ +#define HANDLE_WRAP_H_ + +namespace node { + +class HandleWrap { + public: + static void Initialize(v8::Handle<v8::Object> target); + static v8::Handle<v8::Value> Close(const v8::Arguments& args); + + protected: + HandleWrap(v8::Handle<v8::Object> object, uv_handle_t* handle); + virtual ~HandleWrap(); + + virtual void StateChange() {} + + v8::Persistent<v8::Object> object_; + + private: + static void OnClose(uv_handle_t* handle); + // Using double underscore due to handle_ member in tcp_wrap. Probably + // tcp_wrap should rename it's member to 'handle'. + uv_handle_t* handle__; +}; + + +} // namespace node + + +#endif // HANDLE_WRAP_H_ diff --git a/src/stream_wrap.cc b/src/stream_wrap.cc index df509c485..3da51d960 100644 --- a/src/stream_wrap.cc +++ b/src/stream_wrap.cc @@ -1,5 +1,6 @@ #include <node.h> #include <node_buffer.h> +#include <handle_wrap.h> #include <stream_wrap.h> #include <req_wrap.h> @@ -43,10 +44,10 @@ typedef class ReqWrap<uv_write_t> WriteWrap; static size_t slab_used; static uv_stream_t* handle_that_last_alloced; -Persistent<String> slab_sym; -Persistent<String> buffer_sym; -Persistent<String> write_queue_size_sym; -bool initialized; +static Persistent<String> slab_sym; +static Persistent<String> buffer_sym; +static Persistent<String> write_queue_size_sym; +static bool initialized; void StreamWrap::Initialize(Handle<Object> target) { @@ -58,6 +59,8 @@ void StreamWrap::Initialize(Handle<Object> target) { HandleScope scope; + HandleWrap::Initialize(target); + slab_sym = Persistent<String>::New(String::NewSymbol("slab")); buffer_sym = Persistent<String>::New(String::NewSymbol("buffer")); write_queue_size_sym = @@ -65,40 +68,15 @@ void StreamWrap::Initialize(Handle<Object> target) { } -StreamWrap::StreamWrap(Handle<Object> object, uv_stream_t* stream) { - HandleScope scope; - +StreamWrap::StreamWrap(Handle<Object> object, uv_stream_t* stream) + : HandleWrap(object, (uv_handle_t*)stream) { stream_ = stream; stream->data = this; - assert(object_.IsEmpty()); - assert(object->InternalFieldCount() > 0); - object_ = v8::Persistent<v8::Object>::New(object); - object_->SetPointerInInternalField(0, this); - UpdateWriteQueueSize(); } -StreamWrap::~StreamWrap() { - assert(object_.IsEmpty()); -} - - -// Free the C++ object on the close callback. -void StreamWrap::OnClose(uv_handle_t* handle) { - StreamWrap* wrap = static_cast<StreamWrap*>(handle->data); - - // The wrap object should still be there. - assert(wrap->object_.IsEmpty() == false); - - wrap->object_->SetPointerInInternalField(0, NULL); - wrap->object_.Dispose(); - wrap->object_.Clear(); - delete wrap; -} - - void StreamWrap::UpdateWriteQueueSize() { object_->Set(write_queue_size_sym, Integer::New(stream_->write_queue_size)); } @@ -224,25 +202,6 @@ void StreamWrap::OnRead(uv_stream_t* handle, ssize_t nread, uv_buf_t buf) { } } -// TODO: share me? -Handle<Value> StreamWrap::Close(const Arguments& args) { - HandleScope scope; - - UNWRAP - - assert(!wrap->object_.IsEmpty()); - int r = uv_close((uv_handle_t*) wrap->stream_, OnClose); - - if (r) { - SetErrno(uv_last_error().code); - - wrap->object_->SetPointerInInternalField(0, NULL); - wrap->object_.Dispose(); - wrap->object_.Clear(); - } - return scope.Close(Integer::New(r)); -} - Handle<Value> StreamWrap::Write(const Arguments& args) { HandleScope scope; diff --git a/src/stream_wrap.h b/src/stream_wrap.h index fb233a447..d1b442fa8 100644 --- a/src/stream_wrap.h +++ b/src/stream_wrap.h @@ -1,9 +1,13 @@ #ifndef STREAM_WRAP_H_ #define STREAM_WRAP_H_ +#include <v8.h> +#include <node.h> +#include <handle_wrap.h> + namespace node { -class StreamWrap { +class StreamWrap : public HandleWrap { public: static void Initialize(v8::Handle<v8::Object> target); @@ -12,13 +16,11 @@ class StreamWrap { static v8::Handle<v8::Value> ReadStart(const v8::Arguments& args); static v8::Handle<v8::Value> ReadStop(const v8::Arguments& args); static v8::Handle<v8::Value> Shutdown(const v8::Arguments& args); - static v8::Handle<v8::Value> Close(const v8::Arguments& args); protected: StreamWrap(v8::Handle<v8::Object> object, uv_stream_t* stream); - ~StreamWrap(); - - v8::Persistent<v8::Object> object_; + virtual ~StreamWrap() { } + void StateChange() { } private: void UpdateWriteQueueSize(); @@ -29,7 +31,6 @@ class StreamWrap { static uv_buf_t OnAlloc(uv_stream_t* handle, size_t suggested_size); static void OnRead(uv_stream_t* handle, ssize_t nread, uv_buf_t buf); static void AfterShutdown(uv_shutdown_t* req, int status); - static void OnClose(uv_handle_t* handle); size_t slab_offset_; uv_stream_t* stream_; diff --git a/src/tcp_wrap.cc b/src/tcp_wrap.cc index cbeb4a3d7..fd4552c97 100644 --- a/src/tcp_wrap.cc +++ b/src/tcp_wrap.cc @@ -1,6 +1,7 @@ #include <node.h> #include <node_buffer.h> #include <req_wrap.h> +#include <handle_wrap.h> #include <stream_wrap.h> // Temporary hack: libuv should provide uv_inet_pton and uv_inet_ntop. @@ -75,10 +76,11 @@ static Persistent<String> port_symbol; typedef class ReqWrap<uv_connect_t> ConnectWrap; -class TCPWrap : StreamWrap { +class TCPWrap : public StreamWrap { public: static void Initialize(Handle<Object> target) { + HandleWrap::Initialize(target); StreamWrap::Initialize(target); HandleScope scope; @@ -88,11 +90,12 @@ class TCPWrap : StreamWrap { t->InstanceTemplate()->SetInternalFieldCount(1); + NODE_SET_PROTOTYPE_METHOD(t, "close", HandleWrap::Close); + 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); - NODE_SET_PROTOTYPE_METHOD(t, "close", StreamWrap::Close); NODE_SET_PROTOTYPE_METHOD(t, "bind", Bind); NODE_SET_PROTOTYPE_METHOD(t, "listen", Listen); diff --git a/src/timer_wrap.cc b/src/timer_wrap.cc index 87ccbe224..3d45946ce 100644 --- a/src/timer_wrap.cc +++ b/src/timer_wrap.cc @@ -1,4 +1,5 @@ #include <node.h> +#include <handle_wrap.h> // Rules: // @@ -48,21 +49,24 @@ using v8::Arguments; using v8::Integer; -class TimerWrap { +class TimerWrap : public HandleWrap { public: static void Initialize(Handle<Object> target) { HandleScope scope; + HandleWrap::Initialize(target); + Local<FunctionTemplate> constructor = FunctionTemplate::New(New); constructor->InstanceTemplate()->SetInternalFieldCount(1); constructor->SetClassName(String::NewSymbol("Timer")); + NODE_SET_PROTOTYPE_METHOD(constructor, "close", HandleWrap::Close); + NODE_SET_PROTOTYPE_METHOD(constructor, "start", Start); NODE_SET_PROTOTYPE_METHOD(constructor, "stop", Stop); NODE_SET_PROTOTYPE_METHOD(constructor, "setRepeat", SetRepeat); NODE_SET_PROTOTYPE_METHOD(constructor, "getRepeat", GetRepeat); NODE_SET_PROTOTYPE_METHOD(constructor, "again", Again); - NODE_SET_PROTOTYPE_METHOD(constructor, "close", Close); target->Set(String::NewSymbol("Timer"), constructor->GetFunction()); } @@ -81,16 +85,11 @@ class TimerWrap { return scope.Close(args.This()); } - TimerWrap(Handle<Object> object) { + TimerWrap(Handle<Object> object) + : HandleWrap(object, (uv_handle_t*) &handle_) { active_ = false; int r = uv_timer_init(&handle_); handle_.data = this; - assert(r == 0); // How do we proxy this error up to javascript? - // Suggestion: uv_timer_init() returns void. - assert(object_.IsEmpty()); - assert(object->InternalFieldCount() > 0); - object_ = v8::Persistent<v8::Object>::New(object); - object_->SetPointerInInternalField(0, this); // uv_timer_init adds a loop reference. (That is, it calls uv_ref.) This // is not the behavior we want in Node. Timers should not increase the @@ -100,7 +99,6 @@ class TimerWrap { ~TimerWrap() { if (!active_) uv_ref(); - assert(object_.IsEmpty()); } void StateChange() { @@ -118,12 +116,6 @@ class TimerWrap { } } - // Free the C++ object on the close callback. - static void OnClose(uv_handle_t* handle) { - TimerWrap* wrap = static_cast<TimerWrap*>(handle->data); - delete wrap; - } - static Handle<Value> Start(const Arguments& args) { HandleScope scope; @@ -194,26 +186,6 @@ class TimerWrap { return scope.Close(Integer::New(repeat)); } - // TODO: share me? - static Handle<Value> Close(const Arguments& args) { - HandleScope scope; - - UNWRAP - - int r = uv_close((uv_handle_t*) &wrap->handle_, OnClose); - - if (r) SetErrno(uv_last_error().code); - - wrap->StateChange(); - - assert(!wrap->object_.IsEmpty()); - wrap->object_->SetPointerInInternalField(0, NULL); - wrap->object_.Dispose(); - wrap->object_.Clear(); - - return scope.Close(Integer::New(r)); - } - static void OnTimeout(uv_timer_t* handle, int status) { HandleScope scope; @@ -227,7 +199,6 @@ class TimerWrap { } uv_timer_t handle_; - Persistent<Object> object_; // This member is set false initially. When the timer is turned // on uv_ref is called. When the timer is turned off uv_unref is // called. Used to mirror libev semantics. @@ -846,6 +846,7 @@ def build(bld): src/node_dtrace.cc src/node_string.cc src/timer_wrap.cc + src/handle_wrap.cc src/stream_wrap.cc src/tcp_wrap.cc src/pipe_wrap.cc |