Browse Source

Abstract out HandleWrap class

v0.7.4-release
Ryan Dahl 14 years ago
parent
commit
0c7bf8132e
  1. 89
      src/handle_wrap.cc
  2. 30
      src/handle_wrap.h
  3. 59
      src/stream_wrap.cc
  4. 13
      src/stream_wrap.h
  5. 7
      src/tcp_wrap.cc
  6. 45
      src/timer_wrap.cc
  7. 1
      wscript

89
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

30
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_

59
src/stream_wrap.cc

@ -1,5 +1,6 @@
#include <node.h> #include <node.h>
#include <node_buffer.h> #include <node_buffer.h>
#include <handle_wrap.h>
#include <stream_wrap.h> #include <stream_wrap.h>
#include <req_wrap.h> #include <req_wrap.h>
@ -43,10 +44,10 @@ typedef class ReqWrap<uv_write_t> WriteWrap;
static size_t slab_used; static size_t slab_used;
static uv_stream_t* handle_that_last_alloced; static uv_stream_t* handle_that_last_alloced;
Persistent<String> slab_sym; static Persistent<String> slab_sym;
Persistent<String> buffer_sym; static Persistent<String> buffer_sym;
Persistent<String> write_queue_size_sym; static Persistent<String> write_queue_size_sym;
bool initialized; static bool initialized;
void StreamWrap::Initialize(Handle<Object> target) { void StreamWrap::Initialize(Handle<Object> target) {
@ -58,6 +59,8 @@ void StreamWrap::Initialize(Handle<Object> target) {
HandleScope scope; HandleScope scope;
HandleWrap::Initialize(target);
slab_sym = Persistent<String>::New(String::NewSymbol("slab")); slab_sym = Persistent<String>::New(String::NewSymbol("slab"));
buffer_sym = Persistent<String>::New(String::NewSymbol("buffer")); buffer_sym = Persistent<String>::New(String::NewSymbol("buffer"));
write_queue_size_sym = write_queue_size_sym =
@ -65,40 +68,15 @@ void StreamWrap::Initialize(Handle<Object> target) {
} }
StreamWrap::StreamWrap(Handle<Object> object, uv_stream_t* stream) { StreamWrap::StreamWrap(Handle<Object> object, uv_stream_t* stream)
HandleScope scope; : HandleWrap(object, (uv_handle_t*)stream) {
stream_ = stream; stream_ = stream;
stream->data = this; stream->data = this;
assert(object_.IsEmpty());
assert(object->InternalFieldCount() > 0);
object_ = v8::Persistent<v8::Object>::New(object);
object_->SetPointerInInternalField(0, this);
UpdateWriteQueueSize(); 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() { void StreamWrap::UpdateWriteQueueSize() {
object_->Set(write_queue_size_sym, Integer::New(stream_->write_queue_size)); 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) { Handle<Value> StreamWrap::Write(const Arguments& args) {
HandleScope scope; HandleScope scope;

13
src/stream_wrap.h

@ -1,9 +1,13 @@
#ifndef STREAM_WRAP_H_ #ifndef STREAM_WRAP_H_
#define STREAM_WRAP_H_ #define STREAM_WRAP_H_
#include <v8.h>
#include <node.h>
#include <handle_wrap.h>
namespace node { namespace node {
class StreamWrap { class StreamWrap : public HandleWrap {
public: public:
static void Initialize(v8::Handle<v8::Object> target); 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> ReadStart(const v8::Arguments& args);
static v8::Handle<v8::Value> ReadStop(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> Shutdown(const v8::Arguments& args);
static v8::Handle<v8::Value> Close(const v8::Arguments& args);
protected: protected:
StreamWrap(v8::Handle<v8::Object> object, uv_stream_t* stream); StreamWrap(v8::Handle<v8::Object> object, uv_stream_t* stream);
~StreamWrap(); virtual ~StreamWrap() { }
void StateChange() { }
v8::Persistent<v8::Object> object_;
private: private:
void UpdateWriteQueueSize(); void UpdateWriteQueueSize();
@ -29,7 +31,6 @@ class StreamWrap {
static uv_buf_t OnAlloc(uv_stream_t* handle, size_t suggested_size); 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 OnRead(uv_stream_t* handle, ssize_t nread, uv_buf_t buf);
static void AfterShutdown(uv_shutdown_t* req, int status); static void AfterShutdown(uv_shutdown_t* req, int status);
static void OnClose(uv_handle_t* handle);
size_t slab_offset_; size_t slab_offset_;
uv_stream_t* stream_; uv_stream_t* stream_;

7
src/tcp_wrap.cc

@ -1,6 +1,7 @@
#include <node.h> #include <node.h>
#include <node_buffer.h> #include <node_buffer.h>
#include <req_wrap.h> #include <req_wrap.h>
#include <handle_wrap.h>
#include <stream_wrap.h> #include <stream_wrap.h>
// Temporary hack: libuv should provide uv_inet_pton and uv_inet_ntop. // 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; typedef class ReqWrap<uv_connect_t> ConnectWrap;
class TCPWrap : StreamWrap { class TCPWrap : public StreamWrap {
public: public:
static void Initialize(Handle<Object> target) { static void Initialize(Handle<Object> target) {
HandleWrap::Initialize(target);
StreamWrap::Initialize(target); StreamWrap::Initialize(target);
HandleScope scope; HandleScope scope;
@ -88,11 +90,12 @@ class TCPWrap : StreamWrap {
t->InstanceTemplate()->SetInternalFieldCount(1); 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, "readStart", StreamWrap::ReadStart);
NODE_SET_PROTOTYPE_METHOD(t, "readStop", StreamWrap::ReadStop); NODE_SET_PROTOTYPE_METHOD(t, "readStop", StreamWrap::ReadStop);
NODE_SET_PROTOTYPE_METHOD(t, "write", StreamWrap::Write); NODE_SET_PROTOTYPE_METHOD(t, "write", StreamWrap::Write);
NODE_SET_PROTOTYPE_METHOD(t, "shutdown", StreamWrap::Shutdown); 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, "bind", Bind);
NODE_SET_PROTOTYPE_METHOD(t, "listen", Listen); NODE_SET_PROTOTYPE_METHOD(t, "listen", Listen);

45
src/timer_wrap.cc

@ -1,4 +1,5 @@
#include <node.h> #include <node.h>
#include <handle_wrap.h>
// Rules: // Rules:
// //
@ -48,21 +49,24 @@ using v8::Arguments;
using v8::Integer; using v8::Integer;
class TimerWrap { class TimerWrap : public HandleWrap {
public: public:
static void Initialize(Handle<Object> target) { static void Initialize(Handle<Object> target) {
HandleScope scope; HandleScope scope;
HandleWrap::Initialize(target);
Local<FunctionTemplate> constructor = FunctionTemplate::New(New); Local<FunctionTemplate> constructor = FunctionTemplate::New(New);
constructor->InstanceTemplate()->SetInternalFieldCount(1); constructor->InstanceTemplate()->SetInternalFieldCount(1);
constructor->SetClassName(String::NewSymbol("Timer")); 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, "start", Start);
NODE_SET_PROTOTYPE_METHOD(constructor, "stop", Stop); NODE_SET_PROTOTYPE_METHOD(constructor, "stop", Stop);
NODE_SET_PROTOTYPE_METHOD(constructor, "setRepeat", SetRepeat); NODE_SET_PROTOTYPE_METHOD(constructor, "setRepeat", SetRepeat);
NODE_SET_PROTOTYPE_METHOD(constructor, "getRepeat", GetRepeat); NODE_SET_PROTOTYPE_METHOD(constructor, "getRepeat", GetRepeat);
NODE_SET_PROTOTYPE_METHOD(constructor, "again", Again); NODE_SET_PROTOTYPE_METHOD(constructor, "again", Again);
NODE_SET_PROTOTYPE_METHOD(constructor, "close", Close);
target->Set(String::NewSymbol("Timer"), constructor->GetFunction()); target->Set(String::NewSymbol("Timer"), constructor->GetFunction());
} }
@ -81,16 +85,11 @@ class TimerWrap {
return scope.Close(args.This()); return scope.Close(args.This());
} }
TimerWrap(Handle<Object> object) { TimerWrap(Handle<Object> object)
: HandleWrap(object, (uv_handle_t*) &handle_) {
active_ = false; active_ = false;
int r = uv_timer_init(&handle_); int r = uv_timer_init(&handle_);
handle_.data = this; 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 // 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 // is not the behavior we want in Node. Timers should not increase the
@ -100,7 +99,6 @@ class TimerWrap {
~TimerWrap() { ~TimerWrap() {
if (!active_) uv_ref(); if (!active_) uv_ref();
assert(object_.IsEmpty());
} }
void StateChange() { 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) { static Handle<Value> Start(const Arguments& args) {
HandleScope scope; HandleScope scope;
@ -194,26 +186,6 @@ class TimerWrap {
return scope.Close(Integer::New(repeat)); 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) { static void OnTimeout(uv_timer_t* handle, int status) {
HandleScope scope; HandleScope scope;
@ -227,7 +199,6 @@ class TimerWrap {
} }
uv_timer_t handle_; uv_timer_t handle_;
Persistent<Object> object_;
// This member is set false initially. When the timer is turned // 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 // on uv_ref is called. When the timer is turned off uv_unref is
// called. Used to mirror libev semantics. // called. Used to mirror libev semantics.

1
wscript

@ -846,6 +846,7 @@ def build(bld):
src/node_dtrace.cc src/node_dtrace.cc
src/node_string.cc src/node_string.cc
src/timer_wrap.cc src/timer_wrap.cc
src/handle_wrap.cc
src/stream_wrap.cc src/stream_wrap.cc
src/tcp_wrap.cc src/tcp_wrap.cc
src/pipe_wrap.cc src/pipe_wrap.cc

Loading…
Cancel
Save