domain: share object and state with native land

Change process.domain to use a getter/setter and access that property
via an array index. These are much faster to get from c++, and it can be
passed to _setupDomainUse and stored as a Persistent<Array>.

InDomain() and GetDomain() as trivial ways to access the domain
information in the native layer. Important because we'll be able to
quickly access if a domain is active. Instead of just whether the domain
module has been loaded.
This commit is contained in:
Trevor Norris 2013-08-06 17:01:44 -07:00
parent 2ef1782bbc
commit 3f5d5847e2
4 changed files with 61 additions and 13 deletions

View File

@ -32,8 +32,25 @@ var endMethods = ['end', 'abort', 'destroy', 'destroySoon'];
// a few side effects.
events.usingDomains = true;
// overwrite process.domain with a getter/setter that will allow for more
// effective optimizations
var _domain = [null];
Object.defineProperty(process, 'domain', {
enumerable: true,
get: function() {
return _domain[0];
},
set: function(arg) {
return _domain[0] = arg;
}
});
// objects with external array data are excellent ways to communicate state
// between js and c++ w/o much overhead
var _domain_flag = {};
// let the process know we're using domains
process._setupDomainUse();
process._setupDomainUse(_domain, _domain_flag);
exports.Domain = Domain;
@ -64,6 +81,7 @@ Domain.prototype.enter = function() {
// to push it onto the stack so that we can pop it later.
exports.active = process.domain = this;
stack.push(this);
_domain_flag[0] = stack.length;
};
Domain.prototype.exit = function() {
@ -74,6 +92,7 @@ Domain.prototype.exit = function() {
do {
d = stack.pop();
} while (d && d !== this);
_domain_flag[0] = stack.length;
exports.active = stack[stack.length - 1];
process.domain = exports.active;

View File

@ -132,6 +132,7 @@ Persistent<Object> process_p;
static Persistent<Function> process_tickCallback;
static Persistent<Object> binding_cache;
static Persistent<Array> module_load_list;
static Persistent<Array> p_domain_box;
static Cached<String> exports_symbol;
@ -183,6 +184,11 @@ static struct {
uint32_t last_threw;
} tick_infobox;
// easily communicate domain depth
static struct {
uint32_t count;
} domain_flag;
#ifdef OPENSSL_NPN_NEGOTIATED
static bool use_npn = true;
#else
@ -917,6 +923,33 @@ void SetupDomainUse(const FunctionCallbackInfo<Value>& args) {
Local<Function> tdc = tdc_v.As<Function>();
process->Set(FIXED_ONE_BYTE_STRING(node_isolate, "_tickCallback"), tdc);
process_tickCallback.Reset(node_isolate, tdc);
if (!args[0]->IsArray()) {
fprintf(stderr, "_setupDomainUse first argument must be an array\n");
abort();
}
p_domain_box.Reset(node_isolate, args[0].As<Array>());
if (!args[1]->IsObject()) {
fprintf(stderr, "_setupDomainUse second argument must be an object\n");
abort();
}
Local<Object> flag = args[1].As<Object>();
flag->SetIndexedPropertiesToExternalArrayData(&domain_flag,
kExternalUnsignedIntArray,
1);
}
bool InDomain() {
return using_domains && domain_flag.count > 0;
}
Handle<Value> GetDomain() {
// no domain can exist if no domain module has been loaded
if (!InDomain() || p_domain_box.IsEmpty())
return Null(node_isolate);
return PersistentToLocal(node_isolate, p_domain_box)->Get(0);
}

View File

@ -218,9 +218,6 @@ NO_RETURN void FatalError(const char* location, const char* message);
abort(); \
}
// allow for quick domain check
extern bool using_domains;
enum Endianness {
kLittleEndian, // _Not_ LITTLE_ENDIAN, clashes with endian.h.
kBigEndian
@ -378,6 +375,10 @@ inline v8::Local<v8::String> OneByteString(v8::Isolate* isolate,
length);
}
bool InDomain();
v8::Handle<v8::Value> GetDomain();
} // namespace node
#endif // SRC_NODE_INTERNALS_H_

View File

@ -23,6 +23,7 @@
#define SRC_REQ_WRAP_H_
#include "node.h"
#include "node_internals.h"
#include "queue.h"
namespace node {
@ -40,16 +41,10 @@ class ReqWrap {
if (object.IsEmpty()) object = v8::Object::New();
persistent().Reset(node_isolate, object);
if (using_domains) {
v8::Local<v8::Value> domain = v8::Context::GetCurrent()
->Global()
->Get(process_symbol)
->ToObject()
->Get(domain_symbol);
if (domain->IsObject()) {
if (InDomain()) {
v8::Local<v8::Value> domain = GetDomain();
if (domain->IsObject())
object->Set(domain_symbol, domain);
}
}
QUEUE_INSERT_TAIL(&req_wrap_queue, &req_wrap_queue_);