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_attach(EV_DEFAULT_UC_ &stdin_writer_);
Attach();
Ref();
return 0;
}
@ -382,7 +382,7 @@ void ChildProcess::MaybeShutdown(void) {
Handle<Value> argv[1] = { Integer::New(exit_code_) };
Emit("exit", 1, argv);
Shutdown();
Detach();
Unref();
}
}

24
src/node_http.cc

@ -72,7 +72,7 @@ HTTPConnection::OnReceive (const void *buf, size_t len)
{
HandleScope scope;
assert(attached_);
assert(refs_);
size_t nparsed;
if (type_ == HTTP_REQUEST) {
@ -90,7 +90,7 @@ void
HTTPConnection::OnEOF ()
{
HandleScope scope;
assert(attached_);
assert(refs_);
if (type_ == HTTP_REQUEST) {
http_parse_requests(&parser_, NULL, 0);
} else {
@ -103,7 +103,7 @@ int
HTTPConnection::on_message_begin (http_parser *parser)
{
HTTPConnection *connection = static_cast<HTTPConnection*> (parser->data);
assert(connection->attached_);
assert(connection->refs_);
connection->Emit("messageBegin", 0, NULL);
return 0;
}
@ -112,7 +112,7 @@ int
HTTPConnection::on_message_complete (http_parser *parser)
{
HTTPConnection *connection = static_cast<HTTPConnection*> (parser->data);
assert(connection->attached_);
assert(connection->refs_);
connection->Emit("messageComplete", 0, NULL);
return 0;
}
@ -122,7 +122,7 @@ HTTPConnection::on_url (http_parser *parser, const char *buf, size_t len)
{
HandleScope scope;
HTTPConnection *connection = static_cast<HTTPConnection*>(parser->data);
assert(connection->attached_);
assert(connection->refs_);
Local<Value> argv[1] = { String::New(buf, len) };
connection->Emit("url", 1, argv);
return 0;
@ -133,7 +133,7 @@ HTTPConnection::on_query_string (http_parser *parser, const char *buf, size_t le
{
HandleScope scope;
HTTPConnection *connection = static_cast<HTTPConnection*>(parser->data);
assert(connection->attached_);
assert(connection->refs_);
Local<Value> argv[1] = { String::New(buf, len) };
connection->Emit("queryString", 1, argv);
return 0;
@ -144,7 +144,7 @@ HTTPConnection::on_path (http_parser *parser, const char *buf, size_t len)
{
HandleScope scope;
HTTPConnection *connection = static_cast<HTTPConnection*>(parser->data);
assert(connection->attached_);
assert(connection->refs_);
Local<Value> argv[1] = { String::New(buf, len) };
connection->Emit("path", 1, argv);
return 0;
@ -155,7 +155,7 @@ HTTPConnection::on_fragment (http_parser *parser, const char *buf, size_t len)
{
HandleScope scope;
HTTPConnection *connection = static_cast<HTTPConnection*>(parser->data);
assert(connection->attached_);
assert(connection->refs_);
Local<Value> argv[1] = { String::New(buf, len) };
connection->Emit("fragment", 1, argv);
return 0;
@ -176,7 +176,7 @@ HTTPConnection::on_header_field (http_parser *parser, const char *buf, size_t le
{
HandleScope scope;
HTTPConnection *connection = static_cast<HTTPConnection*>(parser->data);
assert(connection->attached_);
assert(connection->refs_);
// NORMALIZE
size_t i;
@ -193,7 +193,7 @@ HTTPConnection::on_header_value (http_parser *parser, const char *buf, size_t le
{
HandleScope scope;
HTTPConnection *connection = static_cast<HTTPConnection*>(parser->data);
assert(connection->attached_);
assert(connection->refs_);
Local<Value> argv[1] = { String::New(buf, len) };
connection->Emit("headerValue", 1, argv);
@ -204,7 +204,7 @@ int
HTTPConnection::on_headers_complete (http_parser *parser)
{
HTTPConnection *connection = static_cast<HTTPConnection*> (parser->data);
assert(connection->attached_);
assert(connection->refs_);
HandleScope scope;
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);
HTTPConnection *connection = static_cast<HTTPConnection*> (parser->data);
assert(connection->attached_);
assert(connection->refs_);
HandleScope scope;
// 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().
ev_ref(EV_DEFAULT_UC);
// Attach the object so it doesn't get garbage collected.
connection->Attach();
// Ref the object so it doesn't get garbage collected.
connection->Ref();
// For the moment I will do DNS lookups in the eio thread pool. This is
// 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);
struct addrinfo *address = NULL;
assert(connection->attached_);
assert(connection->refs_);
assert(connection->resolving_);
req->result = getaddrinfo(connection->host_, connection->port_,
@ -281,7 +281,7 @@ int Connection::AfterResolve(eio_req *req) {
Connection *connection = static_cast<Connection*> (req->data);
assert(connection->resolving_);
assert(connection->attached_);
assert(connection->refs_);
struct addrinfo *address = NULL,
*address_list = static_cast<struct addrinfo *>(req->ptr2);
@ -311,7 +311,7 @@ int Connection::AfterResolve(eio_req *req) {
connection->OnClose();
connection->Detach();
connection->Unref();
out:
return 0;
@ -537,7 +537,7 @@ Handle<Value> Connection::ForceClose(const Arguments& args) {
assert(connection);
connection->ForceClose();
connection->Detach();
connection->Unref();
return Undefined();
}
@ -709,7 +709,7 @@ Connection* Server::OnConnection(struct sockaddr *addr) {
}
#endif
connection->Attach();
connection->Ref();
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) {
Connection *connection = static_cast<Connection*>(s->data);
assert(connection->attached_);
assert(connection->refs_);
if (len == 0)
connection->OnEOF();
else
@ -149,9 +149,9 @@ class Connection : public EventEmitter {
connection->OnClose();
assert(connection->attached_);
assert(connection->refs_);
connection->Detach();
connection->Unref();
}
static void on_timeout(evcom_stream *s) {
@ -204,7 +204,7 @@ class Server : public EventEmitter {
int r = evcom_server_listen(&server_, address, backlog);
if (r != 0) return r;
evcom_server_attach(EV_DEFAULT_ &server_);
Attach();
Ref();
return 0;
}
@ -230,7 +230,7 @@ class Server : public EventEmitter {
Server *server = static_cast<Server*>(s->data);
evcom_server_detach(s);
server->OnClose(s->errorno);
server->Detach();
server->Unref();
}
evcom_server server_;

26
src/node_object_wrap.h

@ -9,7 +9,7 @@ namespace node {
class ObjectWrap {
public:
ObjectWrap ( ) {
attached_ = 0;
refs_ = 0;
}
virtual ~ObjectWrap ( ) {
@ -45,42 +45,42 @@ class ObjectWrap {
handle_.MakeWeak(this, WeakCallback);
}
/* Attach() marks the object as being attached to an event loop.
* Attached objects will not be garbage collected, even if
/* Ref() marks the object as being attached to an event loop.
* Refed objects will not be garbage collected, even if
* all references are lost.
*/
virtual void Attach() {
virtual void Ref() {
assert(!handle_.IsEmpty());
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
* 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
* (A "weak reference" means an object that only has a
* persistant handle.)
*
* DO NOT CALL THIS FROM DESTRUCTOR
*/
virtual void Detach() {
virtual void Unref() {
assert(!handle_.IsEmpty());
assert(handle_.IsWeak());
assert(attached_ > 0);
attached_--;
if (attached_ == 0 && handle_.IsNearDeath()) delete this;
assert(refs_ > 0);
refs_--;
if (refs_ == 0 && handle_.IsNearDeath()) delete this;
}
v8::Persistent<v8::Object> handle_; // ro
int attached_; // ro
int refs_; // ro
private:
static void WeakCallback (v8::Persistent<v8::Value> value, void *data)
{
ObjectWrap *obj = static_cast<ObjectWrap*>(data);
assert(value == obj->handle_);
if (obj->attached_ == 0) {
if (obj->refs_ == 0) {
delete obj;
} else {
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_unref(EV_DEFAULT_UC);
handler->Attach();
handler->Ref();
return args.This();
}
@ -67,7 +67,7 @@ Handle<Value> SignalHandler::Stop(const Arguments& args) {
SignalHandler *handler = ObjectWrap::Unwrap<SignalHandler>(args.Holder());
ev_ref(EV_DEFAULT_UC);
ev_signal_stop(EV_DEFAULT_UC_ &handler->watcher_);
handler->Detach();
handler->Unref();
return Undefined();
}

4
src/node_stat.cc

@ -74,7 +74,7 @@ Handle<Value> Stat::Start(const Arguments& args) {
ev_unref(EV_DEFAULT_UC);
}
handler->Attach();
handler->Ref();
return Undefined();
}
@ -95,7 +95,7 @@ void Stat::Stop () {
ev_stat_stop(EV_DEFAULT_UC_ &watcher_);
free(path_);
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);
if (timer->watcher_.repeat == 0) timer->Detach();
if (timer->watcher_.repeat == 0) timer->Unref();
}
Timer::~Timer ()
@ -99,7 +99,7 @@ Timer::Start (const Arguments& args)
timer->watcher_.data = timer;
ev_timer_start(EV_DEFAULT_UC_ &timer->watcher_);
timer->Attach();
timer->Ref();
return Undefined();
}
@ -110,7 +110,7 @@ Timer::Stop (const Arguments& args)
Timer *timer = ObjectWrap::Unwrap<Timer>(args.Holder());
if (ev_is_active(&timer->watcher_)) {
ev_timer_stop(EV_DEFAULT_UC_ &timer->watcher_);
timer->Detach();
timer->Unref();
}
return Undefined();
}

Loading…
Cancel
Save