Browse Source

Attach/Detach -> Ref/Unref

v0.7.4-release
Ryan Dahl 15 years ago
parent
commit
c1baa70fe5
  1. 71
      src/node_binary.cc
  2. 56
      src/node_binary.h
  3. 4
      src/node_child_process.cc
  4. 24
      src/node_http.cc
  5. 14
      src/node_net.cc
  6. 10
      src/node_net.h
  7. 26
      src/node_object_wrap.h
  8. 4
      src/node_signal_handler.cc
  9. 4
      src/node_stat.cc
  10. 6
      src/node_timer.cc

71
src/node_binary.cc

@ -0,0 +1,71 @@
// Copyright 2009, Ryan Dahl <ry@tinyclouds.org>. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <node_byte_string.h>
namespace node {
using namespace v8;
static v8::Persistent<v8::FunctionTemplate> byte_string_template;
// V8 contstructor
static Handle<Value> New(const Arguments& args) {
HandleScope scope;
// somehow create the c object.
byte_string *bs = malloc(sizeof(byte_string) + length);
bs->handle = v8::Persistent<v8::Object>::New(args.This());
bs->handle->SetInternalField(0, v8::External::New(bs));
return args.This();
}
byte_string* byte_string_new(size_t length)
{
byte_string_template->GetFunction()->NewInstance();
// unwrap handle
return bs;
}
void byte_string_init(v8::Local<v8::Object> target) {
HandleScope scope;
Local<FunctionTemplate> t = FunctionTemplate::New(New);
byte_string_template = Persistent<FunctionTemplate>::New(t);
byte_string_template->InstanceTemplate()->SetInternalFieldCount(1);
// Set class name for debugging output
byte_string_template->SetClassName(String::NewSymbol("Binary"));
NODE_SET_PROTOTYPE_METHOD(byte_string_template, "toString", ToString);
target->Set(String::NewSymbol("Binary"),
byte_string_template->GetFunction());
}
} // namespace node

56
src/node_binary.h

@ -0,0 +1,56 @@
// Copyright 2009, Ryan Dahl <ry@tinyclouds.org>. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to permit
// persons to whom the Software is furnished to do so, subject to the
// following conditions:
//
// The above copyright notice and this permission notice shall be included
// in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
// OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
// NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
// USE OR OTHER DEALINGS IN THE SOFTWARE.
#ifndef NODE_BYTE_STRING_H_
#define NODE_BYTE_STRING_H_
#include <v8.h>
namespace node {
void byte_string_init(v8::Local<v8::Object> target);
/* Byte string is an immutable chunk of data that can be created from C++
* (byte_string_new()) or from Javascript (new ByteString(string, encoding)). It
* provides a means of passing data through javascript, usually from one C++
* object (like a TCP socket) to another C++ object (like an HTTP parser).
*
* Byte strings are always destructed by the V8 GC. Do not store references
* to byte_string pointers, only create them and pass them into javascript,
* or receive them as arguments out of javascript.
*/
typedef struct {
v8::Persistent<v8::Object> handle;
size_t length;
char bytes[1];
} byte_string;
byte_string* byte_string_new(size_t length);
byte_string* byte_string_unwrap(v8::Handle<v8::Object> handle) {
assert(!handle.IsEmpty());
assert(handle->InternalFieldCount() > 0);
return static_cast<byte_string*>(v8::Handle<v8::External>::Cast(
handle->GetInternalField(0))->Value());
}
} // namespace node
#endif // NODE_BYTE_STRING_H_

4
src/node_child_process.cc

@ -338,7 +338,7 @@ int ChildProcess::Spawn(const char *file, char *const args[], char *const env[])
evcom_writer_set(&stdin_writer_, stdin_fd_); evcom_writer_set(&stdin_writer_, stdin_fd_);
evcom_writer_attach(EV_DEFAULT_UC_ &stdin_writer_); evcom_writer_attach(EV_DEFAULT_UC_ &stdin_writer_);
Attach(); Ref();
return 0; return 0;
} }
@ -382,7 +382,7 @@ void ChildProcess::MaybeShutdown(void) {
Handle<Value> argv[1] = { Integer::New(exit_code_) }; Handle<Value> argv[1] = { Integer::New(exit_code_) };
Emit("exit", 1, argv); Emit("exit", 1, argv);
Shutdown(); Shutdown();
Detach(); Unref();
} }
} }

24
src/node_http.cc

@ -72,7 +72,7 @@ HTTPConnection::OnReceive (const void *buf, size_t len)
{ {
HandleScope scope; HandleScope scope;
assert(attached_); assert(refs_);
size_t nparsed; size_t nparsed;
if (type_ == HTTP_REQUEST) { if (type_ == HTTP_REQUEST) {
@ -90,7 +90,7 @@ void
HTTPConnection::OnEOF () HTTPConnection::OnEOF ()
{ {
HandleScope scope; HandleScope scope;
assert(attached_); assert(refs_);
if (type_ == HTTP_REQUEST) { if (type_ == HTTP_REQUEST) {
http_parse_requests(&parser_, NULL, 0); http_parse_requests(&parser_, NULL, 0);
} else { } else {
@ -103,7 +103,7 @@ int
HTTPConnection::on_message_begin (http_parser *parser) HTTPConnection::on_message_begin (http_parser *parser)
{ {
HTTPConnection *connection = static_cast<HTTPConnection*> (parser->data); HTTPConnection *connection = static_cast<HTTPConnection*> (parser->data);
assert(connection->attached_); assert(connection->refs_);
connection->Emit("messageBegin", 0, NULL); connection->Emit("messageBegin", 0, NULL);
return 0; return 0;
} }
@ -112,7 +112,7 @@ int
HTTPConnection::on_message_complete (http_parser *parser) HTTPConnection::on_message_complete (http_parser *parser)
{ {
HTTPConnection *connection = static_cast<HTTPConnection*> (parser->data); HTTPConnection *connection = static_cast<HTTPConnection*> (parser->data);
assert(connection->attached_); assert(connection->refs_);
connection->Emit("messageComplete", 0, NULL); connection->Emit("messageComplete", 0, NULL);
return 0; return 0;
} }
@ -122,7 +122,7 @@ HTTPConnection::on_url (http_parser *parser, const char *buf, size_t len)
{ {
HandleScope scope; HandleScope scope;
HTTPConnection *connection = static_cast<HTTPConnection*>(parser->data); HTTPConnection *connection = static_cast<HTTPConnection*>(parser->data);
assert(connection->attached_); assert(connection->refs_);
Local<Value> argv[1] = { String::New(buf, len) }; Local<Value> argv[1] = { String::New(buf, len) };
connection->Emit("url", 1, argv); connection->Emit("url", 1, argv);
return 0; return 0;
@ -133,7 +133,7 @@ HTTPConnection::on_query_string (http_parser *parser, const char *buf, size_t le
{ {
HandleScope scope; HandleScope scope;
HTTPConnection *connection = static_cast<HTTPConnection*>(parser->data); HTTPConnection *connection = static_cast<HTTPConnection*>(parser->data);
assert(connection->attached_); assert(connection->refs_);
Local<Value> argv[1] = { String::New(buf, len) }; Local<Value> argv[1] = { String::New(buf, len) };
connection->Emit("queryString", 1, argv); connection->Emit("queryString", 1, argv);
return 0; return 0;
@ -144,7 +144,7 @@ HTTPConnection::on_path (http_parser *parser, const char *buf, size_t len)
{ {
HandleScope scope; HandleScope scope;
HTTPConnection *connection = static_cast<HTTPConnection*>(parser->data); HTTPConnection *connection = static_cast<HTTPConnection*>(parser->data);
assert(connection->attached_); assert(connection->refs_);
Local<Value> argv[1] = { String::New(buf, len) }; Local<Value> argv[1] = { String::New(buf, len) };
connection->Emit("path", 1, argv); connection->Emit("path", 1, argv);
return 0; return 0;
@ -155,7 +155,7 @@ HTTPConnection::on_fragment (http_parser *parser, const char *buf, size_t len)
{ {
HandleScope scope; HandleScope scope;
HTTPConnection *connection = static_cast<HTTPConnection*>(parser->data); HTTPConnection *connection = static_cast<HTTPConnection*>(parser->data);
assert(connection->attached_); assert(connection->refs_);
Local<Value> argv[1] = { String::New(buf, len) }; Local<Value> argv[1] = { String::New(buf, len) };
connection->Emit("fragment", 1, argv); connection->Emit("fragment", 1, argv);
return 0; return 0;
@ -176,7 +176,7 @@ HTTPConnection::on_header_field (http_parser *parser, const char *buf, size_t le
{ {
HandleScope scope; HandleScope scope;
HTTPConnection *connection = static_cast<HTTPConnection*>(parser->data); HTTPConnection *connection = static_cast<HTTPConnection*>(parser->data);
assert(connection->attached_); assert(connection->refs_);
// NORMALIZE // NORMALIZE
size_t i; size_t i;
@ -193,7 +193,7 @@ HTTPConnection::on_header_value (http_parser *parser, const char *buf, size_t le
{ {
HandleScope scope; HandleScope scope;
HTTPConnection *connection = static_cast<HTTPConnection*>(parser->data); HTTPConnection *connection = static_cast<HTTPConnection*>(parser->data);
assert(connection->attached_); assert(connection->refs_);
Local<Value> argv[1] = { String::New(buf, len) }; Local<Value> argv[1] = { String::New(buf, len) };
connection->Emit("headerValue", 1, argv); connection->Emit("headerValue", 1, argv);
@ -204,7 +204,7 @@ int
HTTPConnection::on_headers_complete (http_parser *parser) HTTPConnection::on_headers_complete (http_parser *parser)
{ {
HTTPConnection *connection = static_cast<HTTPConnection*> (parser->data); HTTPConnection *connection = static_cast<HTTPConnection*> (parser->data);
assert(connection->attached_); assert(connection->refs_);
HandleScope scope; HandleScope scope;
Local<Object> message_info = Object::New(); Local<Object> message_info = Object::New();
@ -251,7 +251,7 @@ HTTPConnection::on_body (http_parser *parser, const char *buf, size_t len)
assert(len != 0); assert(len != 0);
HTTPConnection *connection = static_cast<HTTPConnection*> (parser->data); HTTPConnection *connection = static_cast<HTTPConnection*> (parser->data);
assert(connection->attached_); assert(connection->refs_);
HandleScope scope; HandleScope scope;
// TODO each message should have their encoding. // TODO each message should have their encoding.

14
src/node_net.cc

@ -233,8 +233,8 @@ Handle<Value> Connection::Connect(const Arguments& args) {
// out. Thus we need to add ev_ref() until AfterResolve(). // out. Thus we need to add ev_ref() until AfterResolve().
ev_ref(EV_DEFAULT_UC); ev_ref(EV_DEFAULT_UC);
// Attach the object so it doesn't get garbage collected. // Ref the object so it doesn't get garbage collected.
connection->Attach(); connection->Ref();
// For the moment I will do DNS lookups in the eio thread pool. This is // For the moment I will do DNS lookups in the eio thread pool. This is
// sub-optimal and cannot handle massive numbers of requests. // sub-optimal and cannot handle massive numbers of requests.
@ -252,7 +252,7 @@ int Connection::Resolve(eio_req *req) {
Connection *connection = static_cast<Connection*> (req->data); Connection *connection = static_cast<Connection*> (req->data);
struct addrinfo *address = NULL; struct addrinfo *address = NULL;
assert(connection->attached_); assert(connection->refs_);
assert(connection->resolving_); assert(connection->resolving_);
req->result = getaddrinfo(connection->host_, connection->port_, req->result = getaddrinfo(connection->host_, connection->port_,
@ -281,7 +281,7 @@ int Connection::AfterResolve(eio_req *req) {
Connection *connection = static_cast<Connection*> (req->data); Connection *connection = static_cast<Connection*> (req->data);
assert(connection->resolving_); assert(connection->resolving_);
assert(connection->attached_); assert(connection->refs_);
struct addrinfo *address = NULL, struct addrinfo *address = NULL,
*address_list = static_cast<struct addrinfo *>(req->ptr2); *address_list = static_cast<struct addrinfo *>(req->ptr2);
@ -311,7 +311,7 @@ int Connection::AfterResolve(eio_req *req) {
connection->OnClose(); connection->OnClose();
connection->Detach(); connection->Unref();
out: out:
return 0; return 0;
@ -537,7 +537,7 @@ Handle<Value> Connection::ForceClose(const Arguments& args) {
assert(connection); assert(connection);
connection->ForceClose(); connection->ForceClose();
connection->Detach(); connection->Unref();
return Undefined(); return Undefined();
} }
@ -709,7 +709,7 @@ Connection* Server::OnConnection(struct sockaddr *addr) {
} }
#endif #endif
connection->Attach(); connection->Ref();
return connection; return connection;
} }

10
src/node_net.h

@ -119,7 +119,7 @@ class Connection : public EventEmitter {
static void on_read(evcom_stream *s, const void *buf, size_t len) { static void on_read(evcom_stream *s, const void *buf, size_t len) {
Connection *connection = static_cast<Connection*>(s->data); Connection *connection = static_cast<Connection*>(s->data);
assert(connection->attached_); assert(connection->refs_);
if (len == 0) if (len == 0)
connection->OnEOF(); connection->OnEOF();
else else
@ -149,9 +149,9 @@ class Connection : public EventEmitter {
connection->OnClose(); connection->OnClose();
assert(connection->attached_); assert(connection->refs_);
connection->Detach(); connection->Unref();
} }
static void on_timeout(evcom_stream *s) { static void on_timeout(evcom_stream *s) {
@ -204,7 +204,7 @@ class Server : public EventEmitter {
int r = evcom_server_listen(&server_, address, backlog); int r = evcom_server_listen(&server_, address, backlog);
if (r != 0) return r; if (r != 0) return r;
evcom_server_attach(EV_DEFAULT_ &server_); evcom_server_attach(EV_DEFAULT_ &server_);
Attach(); Ref();
return 0; return 0;
} }
@ -230,7 +230,7 @@ class Server : public EventEmitter {
Server *server = static_cast<Server*>(s->data); Server *server = static_cast<Server*>(s->data);
evcom_server_detach(s); evcom_server_detach(s);
server->OnClose(s->errorno); server->OnClose(s->errorno);
server->Detach(); server->Unref();
} }
evcom_server server_; evcom_server server_;

26
src/node_object_wrap.h

@ -9,7 +9,7 @@ namespace node {
class ObjectWrap { class ObjectWrap {
public: public:
ObjectWrap ( ) { ObjectWrap ( ) {
attached_ = 0; refs_ = 0;
} }
virtual ~ObjectWrap ( ) { virtual ~ObjectWrap ( ) {
@ -45,42 +45,42 @@ class ObjectWrap {
handle_.MakeWeak(this, WeakCallback); handle_.MakeWeak(this, WeakCallback);
} }
/* Attach() marks the object as being attached to an event loop. /* Ref() marks the object as being attached to an event loop.
* Attached objects will not be garbage collected, even if * Refed objects will not be garbage collected, even if
* all references are lost. * all references are lost.
*/ */
virtual void Attach() { virtual void Ref() {
assert(!handle_.IsEmpty()); assert(!handle_.IsEmpty());
assert(handle_.IsWeak()); assert(handle_.IsWeak());
attached_++; refs_++;
} }
/* Detach() marks an object as detached from the event loop. This is its /* Unref() marks an object as detached from the event loop. This is its
* default state. When an object with a "weak" reference changes from * default state. When an object with a "weak" reference changes from
* attached to detached state it will be freed. Be careful not to access * attached to detached state it will be freed. Be careful not to access
* the object after making this call as it might be gone! * the object after making this call as it might be gone!
* (A "weak reference" is v8 terminology for an object that only has a * (A "weak reference" means an object that only has a
* persistant handle.) * persistant handle.)
* *
* DO NOT CALL THIS FROM DESTRUCTOR * DO NOT CALL THIS FROM DESTRUCTOR
*/ */
virtual void Detach() { virtual void Unref() {
assert(!handle_.IsEmpty()); assert(!handle_.IsEmpty());
assert(handle_.IsWeak()); assert(handle_.IsWeak());
assert(attached_ > 0); assert(refs_ > 0);
attached_--; refs_--;
if (attached_ == 0 && handle_.IsNearDeath()) delete this; if (refs_ == 0 && handle_.IsNearDeath()) delete this;
} }
v8::Persistent<v8::Object> handle_; // ro v8::Persistent<v8::Object> handle_; // ro
int attached_; // ro int refs_; // ro
private: private:
static void WeakCallback (v8::Persistent<v8::Value> value, void *data) static void WeakCallback (v8::Persistent<v8::Value> value, void *data)
{ {
ObjectWrap *obj = static_cast<ObjectWrap*>(data); ObjectWrap *obj = static_cast<ObjectWrap*>(data);
assert(value == obj->handle_); assert(value == obj->handle_);
if (obj->attached_ == 0) { if (obj->refs_ == 0) {
delete obj; delete obj;
} else { } else {
obj->MakeWeak(); obj->MakeWeak();

4
src/node_signal_handler.cc

@ -56,7 +56,7 @@ Handle<Value> SignalHandler::New(const Arguments& args) {
ev_signal_start(EV_DEFAULT_UC_ &handler->watcher_); ev_signal_start(EV_DEFAULT_UC_ &handler->watcher_);
ev_unref(EV_DEFAULT_UC); ev_unref(EV_DEFAULT_UC);
handler->Attach(); handler->Ref();
return args.This(); return args.This();
} }
@ -67,7 +67,7 @@ Handle<Value> SignalHandler::Stop(const Arguments& args) {
SignalHandler *handler = ObjectWrap::Unwrap<SignalHandler>(args.Holder()); SignalHandler *handler = ObjectWrap::Unwrap<SignalHandler>(args.Holder());
ev_ref(EV_DEFAULT_UC); ev_ref(EV_DEFAULT_UC);
ev_signal_stop(EV_DEFAULT_UC_ &handler->watcher_); ev_signal_stop(EV_DEFAULT_UC_ &handler->watcher_);
handler->Detach(); handler->Unref();
return Undefined(); return Undefined();
} }

4
src/node_stat.cc

@ -74,7 +74,7 @@ Handle<Value> Stat::Start(const Arguments& args) {
ev_unref(EV_DEFAULT_UC); ev_unref(EV_DEFAULT_UC);
} }
handler->Attach(); handler->Ref();
return Undefined(); return Undefined();
} }
@ -95,7 +95,7 @@ void Stat::Stop () {
ev_stat_stop(EV_DEFAULT_UC_ &watcher_); ev_stat_stop(EV_DEFAULT_UC_ &watcher_);
free(path_); free(path_);
path_ = NULL; path_ = NULL;
Detach(); Unref();
} }
} }

6
src/node_timer.cc

@ -64,7 +64,7 @@ Timer::OnTimeout (EV_P_ ev_timer *watcher, int revents)
timer->Emit("timeout", 0, NULL); timer->Emit("timeout", 0, NULL);
if (timer->watcher_.repeat == 0) timer->Detach(); if (timer->watcher_.repeat == 0) timer->Unref();
} }
Timer::~Timer () Timer::~Timer ()
@ -99,7 +99,7 @@ Timer::Start (const Arguments& args)
timer->watcher_.data = timer; timer->watcher_.data = timer;
ev_timer_start(EV_DEFAULT_UC_ &timer->watcher_); ev_timer_start(EV_DEFAULT_UC_ &timer->watcher_);
timer->Attach(); timer->Ref();
return Undefined(); return Undefined();
} }
@ -110,7 +110,7 @@ Timer::Stop (const Arguments& args)
Timer *timer = ObjectWrap::Unwrap<Timer>(args.Holder()); Timer *timer = ObjectWrap::Unwrap<Timer>(args.Holder());
if (ev_is_active(&timer->watcher_)) { if (ev_is_active(&timer->watcher_)) {
ev_timer_stop(EV_DEFAULT_UC_ &timer->watcher_); ev_timer_stop(EV_DEFAULT_UC_ &timer->watcher_);
timer->Detach(); timer->Unref();
} }
return Undefined(); return Undefined();
} }

Loading…
Cancel
Save