Simplify and cleanup ObjectWrap.
authorRyan <ry@tinyclouds.org>
Fri, 10 Jul 2009 11:38:53 +0000 (13:38 +0200)
committerRyan <ry@tinyclouds.org>
Fri, 10 Jul 2009 11:38:53 +0000 (13:38 +0200)
    Simplify and inline ObjectWrap::Wrap

    Inline and clean up ObjectWrap::Unwrap

    Move ObjectWrap into its own file.

    Remove handle from ObjectWrap constructor. add obj->Wrap(handle)

    Simplify Attach/Detach in ObjectWrap

    Remove ObjectWrap::InformV8ofAllocation. (Too messy/complex.)

13 files changed:
src/events.cc
src/events.h
src/http.cc
src/http.h
src/net.cc
src/net.h
src/node.cc
src/node.h
src/object_wrap.h [new file with mode: 0644]
src/process.cc
src/process.h
src/timer.cc
src/timer.h

index f39d8e7..9967c1c 100644 (file)
@@ -82,8 +82,8 @@ Promise::Create (void)
   Local<Object> handle =
     Promise::constructor_template->GetFunction()->NewInstance();
 
-  Promise *promise = new Promise(handle);
-  ObjectWrap::InformV8ofAllocation(promise);
+  Promise *promise = new Promise();
+  promise->Wrap(handle);
 
   promise->Attach();
   ev_ref(EV_DEFAULT_UC);
index abd1eda..ca3d5fd 100644 (file)
@@ -10,20 +10,17 @@ class EventEmitter : public ObjectWrap {
  public:
   static void Initialize (v8::Handle<v8::Object> target);
   static v8::Persistent<v8::FunctionTemplate> constructor_template;
-  virtual size_t size (void) { return sizeof(EventEmitter); };
 
   bool Emit (const char *type, int argc, v8::Handle<v8::Value> argv[]);
 
  protected:
-  EventEmitter (v8::Handle<v8::Object> handle)
-    : ObjectWrap(handle) { }
+  EventEmitter () : ObjectWrap() { }
 };
 
 class Promise : public EventEmitter {
  public:
   static void Initialize (v8::Handle<v8::Object> target);
   static v8::Persistent<v8::FunctionTemplate> constructor_template;
-  virtual size_t size (void) { return sizeof(Promise); };
  
   bool EmitSuccess (int argc, v8::Handle<v8::Value> argv[]);
   bool EmitError (int argc, v8::Handle<v8::Value> argv[]);
@@ -34,7 +31,7 @@ class Promise : public EventEmitter {
 
  protected:
 
-  Promise (v8::Handle<v8::Object> handle) : EventEmitter(handle) { }
+  Promise () : EventEmitter() { }
 };
 
 } // namespace node
index 42fafb6..6261a90 100644 (file)
@@ -59,8 +59,8 @@ HTTPConnection::NewClient (const Arguments& args)
 {
   HandleScope scope;
 
-  HTTPConnection *connection = new HTTPConnection(args.This(), HTTP_RESPONSE);
-  ObjectWrap::InformV8ofAllocation(connection);
+  HTTPConnection *connection = new HTTPConnection(HTTP_RESPONSE);
+  connection->Wrap(args.This());
 
   return args.This();
 }
@@ -70,8 +70,8 @@ HTTPConnection::NewServer (const Arguments& args)
 {
   HandleScope scope;
 
-  HTTPConnection *connection = new HTTPConnection(args.This(), HTTP_REQUEST);
-  ObjectWrap::InformV8ofAllocation(connection);
+  HTTPConnection *connection = new HTTPConnection(HTTP_REQUEST);
+  connection->Wrap(args.This());
 
   return args.This();
 }
@@ -221,20 +221,6 @@ HTTPConnection::on_body (http_parser *parser, const char *buf, size_t len)
   return 0;
 }
 
-HTTPConnection::HTTPConnection (Handle<Object> handle, enum http_parser_type type)
-  : Connection(handle) 
-{
-  http_parser_init (&parser_, type);
-  parser_.on_message_begin    = on_message_begin;
-  parser_.on_uri              = on_uri;
-  parser_.on_header_field     = on_header_field;
-  parser_.on_header_value     = on_header_value;
-  parser_.on_headers_complete = on_headers_complete;
-  parser_.on_body             = on_body;
-  parser_.on_message_complete = on_message_complete;
-  parser_.data = this;
-}
-
 Persistent<FunctionTemplate> HTTPServer::constructor_template;
 
 void
@@ -254,8 +240,8 @@ HTTPServer::New (const Arguments& args)
 {
   HandleScope scope;
 
-  HTTPServer *s = new HTTPServer(args.This());
-  ObjectWrap::InformV8ofAllocation(s);
+  HTTPServer *server = new HTTPServer();
+  server->Wrap(args.This());
 
   return args.This();
 }
index ee1e810..02392d7 100644 (file)
@@ -14,14 +14,23 @@ public:
   static v8::Persistent<v8::FunctionTemplate> client_constructor_template;
   static v8::Persistent<v8::FunctionTemplate> server_constructor_template;
 
-  virtual size_t size (void) { return sizeof(HTTPConnection); };
-  
 protected:
   static v8::Handle<v8::Value> NewClient (const v8::Arguments& args);
   static v8::Handle<v8::Value> NewServer (const v8::Arguments& args);
 
-  HTTPConnection (v8::Handle<v8::Object> handle, 
-                  enum http_parser_type type);
+  HTTPConnection (enum http_parser_type type)
+    : Connection() 
+  {
+    http_parser_init (&parser_, type);
+    parser_.on_message_begin    = on_message_begin;
+    parser_.on_uri              = on_uri;
+    parser_.on_header_field     = on_header_field;
+    parser_.on_header_value     = on_header_value;
+    parser_.on_headers_complete = on_headers_complete;
+    parser_.on_body             = on_body;
+    parser_.on_message_complete = on_message_complete;
+    parser_.data = this;
+  }
 
   void OnReceive (const void *buf, size_t len);
 
@@ -43,12 +52,10 @@ public:
   static void Initialize (v8::Handle<v8::Object> target);
   static v8::Persistent<v8::FunctionTemplate> constructor_template;
 
-  virtual size_t size (void) { return sizeof(HTTPServer); };
-
 protected:
   static v8::Handle<v8::Value> New (const v8::Arguments& args);
 
-  HTTPServer (v8::Handle<v8::Object> handle) : Server(handle) {}
+  HTTPServer (void) : Server() {}
 
   v8::Handle<v8::FunctionTemplate> GetConnectionTemplate (void);
   Connection* UnwrapConnection (v8::Local<v8::Object> connection);
index 20e6208..61bcbb4 100644 (file)
@@ -96,17 +96,6 @@ Connection::ReadyStateGetter (Local<String> property, const AccessorInfo& info)
   return ThrowException(String::New("This shouldn't happen."));
 }
 
-Connection::Connection (Handle<Object> handle)
-  : EventEmitter(handle) 
-{
-  encoding_ = RAW;
-
-  host_ = NULL;
-  port_ = NULL;
-
-  Init();
-}
-
 void
 Connection::Init (void)
 {
@@ -121,7 +110,6 @@ Connection::Init (void)
   socket_.data = this;
 }
 
-
 Connection::~Connection ()
 {
   static int i = 0;
@@ -138,8 +126,8 @@ Connection::New (const Arguments& args)
 {
   HandleScope scope;
 
-  Connection *c = new Connection(args.This());
-  ObjectWrap::InformV8ofAllocation(c);
+  Connection *connection = new Connection();
+  connection->Wrap(args.This());
 
   return args.This();
 }
@@ -492,26 +480,6 @@ Server::Initialize (Handle<Object> target)
   target->Set(String::NewSymbol("Server"), constructor_template->GetFunction());
 }
 
-Server::Server (Handle<Object> handle) 
-  : EventEmitter(handle) 
-{
-  HandleScope scope;
-
-#if 0
-  // TODO SetOptions
-  handle_->SetHiddenValue(CONNECTION_HANDLER_SYMBOL, connection_handler);
-
-  int backlog = 1024; // default value
-  Local<Value> backlog_v = options->Get(String::NewSymbol("backlog"));
-  if (backlog_v->IsInt32()) {
-    backlog = backlog_v->IntegerValue();
-  }
-#endif
-
-  oi_server_init(&server_, 1024);
-  server_.on_connection = Server::on_connection;
-  server_.data = this;
-}
 
 static Local<String>
 GetAddressString (struct sockaddr *addr)
@@ -589,8 +557,8 @@ Server::New (const Arguments& args)
 {
   HandleScope scope;
 
-  Server *a = new Server(args.This());
-  ObjectWrap::InformV8ofAllocation(a);
+  Server *server = new Server();
+  server->Wrap(args.This());
 
   return args.This();
 }
index e597ee9..1449eb6 100644 (file)
--- a/src/net.h
+++ b/src/net.h
@@ -14,8 +14,6 @@ class Connection : public EventEmitter {
 public:
   static void Initialize (v8::Handle<v8::Object> target);
 
-  virtual size_t size (void) { return sizeof(Connection); };
-
 protected:
   /* v8 interface */
   static v8::Persistent<v8::FunctionTemplate> constructor_template;
@@ -31,8 +29,16 @@ protected:
   static v8::Handle<v8::Value> ReadyStateGetter (v8::Local<v8::String> _,
       const v8::AccessorInfo& info);
 
-  Connection (v8::Handle<v8::Object> handle); 
-  virtual ~Connection ();
+  Connection (void) : EventEmitter() 
+  {
+    encoding_ = RAW;
+
+    host_ = NULL;
+    port_ = NULL;
+
+    Init();
+  }
+  virtual ~Connection (void);
 
   int Connect (struct addrinfo *address) {
     return oi_socket_connect (&socket_, address);
@@ -110,15 +116,18 @@ class Server : public EventEmitter {
 public:
   static void Initialize (v8::Handle<v8::Object> target);
 
-  virtual size_t size (void) { return sizeof(Server); };
-
 protected:
   static v8::Persistent<v8::FunctionTemplate> constructor_template;
   static v8::Handle<v8::Value> New (const v8::Arguments& args);
   static v8::Handle<v8::Value> Listen (const v8::Arguments& args);
   static v8::Handle<v8::Value> Close (const v8::Arguments& args);
 
-  Server (v8::Handle<v8::Object> handle);
+  Server (void) : EventEmitter() 
+  {
+    oi_server_init(&server_, 1024);
+    server_.on_connection = Server::on_connection;
+    server_.data = this;
+  }
   virtual ~Server () { Close(); }
 
   int Listen (struct addrinfo *address) { 
index 988eb08..a60aa78 100644 (file)
@@ -23,83 +23,6 @@ using namespace v8;
 using namespace node;
 using namespace std;
 
-ObjectWrap::~ObjectWrap ( )
-{
-  handle_->SetInternalField(0, Undefined());
-  handle_.Dispose();
-  handle_.Clear(); 
-}
-
-ObjectWrap::ObjectWrap (Handle<Object> handle)
-{
-  // TODO throw exception if it's already set
-  HandleScope scope;
-  handle_ = Persistent<Object>::New(handle);
-
-  Handle<External> external = External::New(this);
-  handle_->SetInternalField(0, external);
-  handle_.MakeWeak(this, ObjectWrap::MakeWeak);
-
-  attach_count_ = 0;
-  weak_ = false;
-}
-
-void
-ObjectWrap::Attach ()
-{
-  attach_count_ += 1;
-}
-
-void
-ObjectWrap::Detach ()
-{
-  if (attach_count_ > 0) attach_count_ -= 1;
-
-  if (weak_ && attach_count_ == 0) {
-    V8::AdjustAmountOfExternalAllocatedMemory(-size());
-    delete this;
-  }
-}
-
-void*
-ObjectWrap::Unwrap (Handle<Object> handle)
-{
-  HandleScope scope;
-  if (handle.IsEmpty()) { 
-    fprintf(stderr, "Node: Tried to unwrap empty object.\n");
-    return NULL;
-  }
-  if ( handle->InternalFieldCount() == 0) {
-    fprintf(stderr, "Node: Tried to unwrap object without internal fields.\n");
-    return NULL;
-  }
-  Local<Value> value = handle->GetInternalField(0);
-  if (value.IsEmpty()) {
-    fprintf(stderr, "Tried to unwrap object with empty internal field.\n");
-    return NULL;
-  }
-  Handle<External> field = Handle<External>::Cast(value);
-  return field->Value();
-}
-
-void
-ObjectWrap::MakeWeak (Persistent<Value> value, void *data)
-{
-  ObjectWrap *obj = static_cast<ObjectWrap*> (data);
-
-  assert(value == obj->handle_);
-
-  obj->weak_ = true;
-  if (obj->attach_count_ == 0)
-    delete obj;
-}
-
-void
-ObjectWrap::InformV8ofAllocation (ObjectWrap *obj)
-{
-  v8::V8::AdjustAmountOfExternalAllocatedMemory(obj->size());
-}
-
 static void
 buf_free (oi_buf *b)
 {
index 00dbd2f..e172d3f 100644 (file)
@@ -6,9 +6,9 @@
 #include <v8.h>
 #include <oi_socket.h>
 
-namespace node {
+#include "object_wrap.h"
 
-#define NODE_UNWRAP(type, value) static_cast<type*>(node::ObjectWrap::Unwrap(value))
+namespace node {
 
 #define NODE_DEFINE_CONSTANT(target, constant)                            \
   (target)->Set(v8::String::NewSymbol(#constant),                         \
@@ -32,40 +32,5 @@ enum encoding ParseEncoding (v8::Handle<v8::Value> encoding_v);
 void FatalException (v8::TryCatch &try_catch); 
 oi_buf * buf_new (size_t size);
 
-class ObjectWrap {
-public:
-  ObjectWrap (v8::Handle<v8::Object> handle);
-  virtual ~ObjectWrap ( );
-
-  virtual size_t size (void) = 0;
-
-  /* This must be called after each new ObjectWrap creation! */
-  static void InformV8ofAllocation (node::ObjectWrap *obj);
-
-protected:
-  static void* Unwrap (v8::Handle<v8::Object> handle);
-
-  /* Attach() marks the object as being attached to an event loop.
-   * Attached objects will not be garbage collected, even if
-   * all references are lost.
-   */
-  void Attach();
-  
-  /* Detach() marks an object as detached from the event loop.  This is its
-   * default state.  When an object with a "weak" reference changes from
-   * attached to detached state it will be freed. Be careful not to access
-   * the object after making this call as it might be gone!
-   * (A "weak reference" is v8 terminology for an object that only has a
-   * persistant handle.)
-   */
-  void Detach();
-  v8::Persistent<v8::Object> handle_;
-
-private:
-  static void MakeWeak (v8::Persistent<v8::Value> _, void *data);
-  int attach_count_;
-  bool weak_;
-};
-
 } // namespace node
 #endif // node_h
diff --git a/src/object_wrap.h b/src/object_wrap.h
new file mode 100644 (file)
index 0000000..619cda1
--- /dev/null
@@ -0,0 +1,80 @@
+#ifndef object_wrap_h
+#define object_wrap_h
+
+#include <v8.h>
+#include <assert.h>
+
+namespace node {
+
+#define NODE_UNWRAP(type, value) static_cast<type*>(node::ObjectWrap::Unwrap(value))
+
+class ObjectWrap {
+public:
+  ObjectWrap ( ) {
+    weak_ = false;
+    attached_ = false;
+  }
+
+  virtual ~ObjectWrap ( ) {
+    if (!handle_.IsEmpty()) {
+      handle_->SetInternalField(0, v8::Undefined());
+      handle_.Dispose();
+      handle_.Clear(); 
+    }
+  }
+
+ protected:
+  static inline void* Unwrap (v8::Handle<v8::Object> handle)
+  {
+    assert(!handle.IsEmpty());
+    assert(handle->InternalFieldCount() == 1);
+    return v8::Handle<v8::External>::Cast(
+        handle->GetInternalField(0))->Value();
+  }
+
+  inline void Wrap(v8::Handle<v8::Object> handle)
+  {
+    assert(handle_.IsEmpty());
+    assert(handle->InternalFieldCount() > 0);
+    handle_ = v8::Persistent<v8::Object>::New(handle);
+    handle_->SetInternalField(0, v8::External::New(this));
+    handle_.MakeWeak(this, MakeWeak);
+  }
+
+  /* Attach() marks the object as being attached to an event loop.
+   * Attached objects will not be garbage collected, even if
+   * all references are lost.
+   */
+  void Attach() {
+    assert(!handle_.IsEmpty());
+    attached_ = true;
+  }
+  
+  /* Detach() marks an object as detached from the event loop.  This is its
+   * default state.  When an object with a "weak" reference changes from
+   * attached to detached state it will be freed. Be careful not to access
+   * the object after making this call as it might be gone!
+   * (A "weak reference" is v8 terminology for an object that only has a
+   * persistant handle.)
+   */
+  void Detach() {
+    assert(!handle_.IsEmpty());
+    attached_ = false;
+    if (weak_) delete this;
+  }
+
+  v8::Persistent<v8::Object> handle_;
+
+ private:
+  static void MakeWeak (v8::Persistent<v8::Value> value, void *data) {
+    ObjectWrap *obj = static_cast<ObjectWrap*>(data);
+    assert(value == obj->handle_);
+    obj->weak_ = true;
+    if (!obj->attached_) delete obj;
+  }
+  bool attached_;
+  bool weak_;
+};
+
+} // namespace node
+#endif // object_wrap_h
index 85f2db7..de93081 100644 (file)
@@ -50,8 +50,8 @@ Process::New (const Arguments& args)
 {
   HandleScope scope;
 
-  Process *p = new Process(args.Holder());
-  ObjectWrap::InformV8ofAllocation(p);
+  Process *p = new Process();
+  p->Wrap(args.Holder());
 
   return args.This();
 }
@@ -168,8 +168,8 @@ Process::Close (const Arguments& args)
   return process->Close() == 0 ? True() : False();
 }
 
-Process::Process (Handle<Object> handle)
-  : EventEmitter(handle)
+Process::Process ()
+  : EventEmitter()
 {
   ev_init(&stdout_watcher_, Process::OnOutput);
   stdout_watcher_.data = this;
index 932d439..a169ccc 100644 (file)
@@ -12,7 +12,6 @@ namespace node {
 class Process : EventEmitter {
  public:
   static void Initialize (v8::Handle<v8::Object> target);
-  virtual size_t size (void) { return sizeof(Process); }
 
  protected:
   static v8::Persistent<v8::FunctionTemplate> constructor_template;
@@ -23,7 +22,7 @@ class Process : EventEmitter {
   static v8::Handle<v8::Value> Kill (const v8::Arguments& args);
   static v8::Handle<v8::Value> PIDGetter (v8::Local<v8::String> _, const v8::AccessorInfo& info);
 
-  Process(v8::Handle<v8::Object> handle);
+  Process();
   ~Process();
 
   int Spawn (const char *command);
index 672732e..0f60fb6 100644 (file)
@@ -81,8 +81,8 @@ Timer::New (const Arguments& args)
 {
   HandleScope scope;
 
-  Timer *t = new Timer(args.Holder());
-  ObjectWrap::InformV8ofAllocation(t);
+  Timer *t = new Timer();
+  t->Wrap(args.Holder());
 
   return args.This();
 }
index f135e7e..ddbf48b 100644 (file)
@@ -12,12 +12,10 @@ class Timer : EventEmitter {
  public:
   static void Initialize (v8::Handle<v8::Object> target);
 
-  virtual size_t size (void) { return sizeof(Timer); }
-
  protected:
   static v8::Persistent<v8::FunctionTemplate> constructor_template;
 
-  Timer (v8::Handle<v8::Object> handle) : EventEmitter (handle) { }
+  Timer () : EventEmitter () { }
   ~Timer();
 
   static v8::Handle<v8::Value> New (const v8::Arguments& args);