Skip to content

Commit

Permalink
isolates: isolate-ify the main loop
Browse files Browse the repository at this point in the history
  • Loading branch information
bnoordhuis committed Dec 29, 2011
1 parent e9f8e28 commit 356992f
Show file tree
Hide file tree
Showing 17 changed files with 198 additions and 75 deletions.
2 changes: 2 additions & 0 deletions node.gyp
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@
'src/node.cc', 'src/node.cc',
'src/node_vars.cc', 'src/node_vars.cc',
'src/node_buffer.cc', 'src/node_buffer.cc',
'src/node_isolate.cc',
'src/node_constants.cc', 'src/node_constants.cc',
'src/node_extensions.cc', 'src/node_extensions.cc',
'src/node_file.cc', 'src/node_file.cc',
Expand All @@ -97,6 +98,7 @@
'src/node.h', 'src/node.h',
'src/node_vars.h', 'src/node_vars.h',
'src/node_buffer.h', 'src/node_buffer.h',
'src/node_isolate.h',
'src/node_constants.h', 'src/node_constants.h',
'src/node_crypto.h', 'src/node_crypto.h',
'src/node_extensions.h', 'src/node_extensions.h',
Expand Down
8 changes: 4 additions & 4 deletions src/cares_wrap.cc
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -607,7 +607,7 @@ void AfterGetAddrInfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res) {


if (status) { if (status) {
// Error // Error
SetErrno(uv_last_error(uv_default_loop())); SetErrno(uv_last_error(NODE_LOOP()));
argv[0] = Local<Value>::New(Null()); argv[0] = Local<Value>::New(Null());
} else { } else {
// Success // Success
Expand Down Expand Up @@ -710,7 +710,7 @@ static Handle<Value> GetAddrInfo(const Arguments& args) {
hints.ai_family = fam; hints.ai_family = fam;
hints.ai_socktype = SOCK_STREAM; hints.ai_socktype = SOCK_STREAM;


int r = uv_getaddrinfo(uv_default_loop(), int r = uv_getaddrinfo(NODE_LOOP(),
&req_wrap->req_, &req_wrap->req_,
AfterGetAddrInfo, AfterGetAddrInfo,
*hostname, *hostname,
Expand All @@ -719,7 +719,7 @@ static Handle<Value> GetAddrInfo(const Arguments& args) {
req_wrap->Dispatched(); req_wrap->Dispatched();


if (r) { if (r) {
SetErrno(uv_last_error(uv_default_loop())); SetErrno(uv_last_error(NODE_LOOP()));
delete req_wrap; delete req_wrap;
return scope.Close(v8::Null()); return scope.Close(v8::Null());
} else { } else {
Expand All @@ -736,7 +736,7 @@ static void Initialize(Handle<Object> target) {
assert(r == ARES_SUCCESS); assert(r == ARES_SUCCESS);


struct ares_options options; struct ares_options options;
uv_ares_init_options(uv_default_loop(), &ares_channel, &options, 0); uv_ares_init_options(NODE_LOOP(), &ares_channel, &options, 0);
assert(r == 0); assert(r == 0);


NODE_SET_METHOD(target, "queryA", Query<QueryAWrap>); NODE_SET_METHOD(target, "queryA", Query<QueryAWrap>);
Expand Down
8 changes: 4 additions & 4 deletions src/fs_event_wrap.cc
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -109,15 +109,15 @@ Handle<Value> FSEventWrap::Start(const Arguments& args) {


String::Utf8Value path(args[0]->ToString()); String::Utf8Value path(args[0]->ToString());


int r = uv_fs_event_init(uv_default_loop(), &wrap->handle_, *path, OnEvent, 0); int r = uv_fs_event_init(NODE_LOOP(), &wrap->handle_, *path, OnEvent, 0);
if (r == 0) { if (r == 0) {
// Check for persistent argument // Check for persistent argument
if (!args[1]->IsTrue()) { if (!args[1]->IsTrue()) {
uv_unref(uv_default_loop()); uv_unref(NODE_LOOP());
} }
wrap->initialized_ = true; wrap->initialized_ = true;
} else { } else {
SetErrno(uv_last_error(uv_default_loop())); SetErrno(uv_last_error(NODE_LOOP()));
} }


return scope.Close(Integer::New(r)); return scope.Close(Integer::New(r));
Expand Down Expand Up @@ -145,7 +145,7 @@ void FSEventWrap::OnEvent(uv_fs_event_t* handle, const char* filename,
// assumption that a rename implicitly means an attribute change. Not too // assumption that a rename implicitly means an attribute change. Not too
// unreasonable, right? Still, we should revisit this before v1.0. // unreasonable, right? Still, we should revisit this before v1.0.
if (status) { if (status) {
SetErrno(uv_last_error(uv_default_loop())); SetErrno(uv_last_error(NODE_LOOP()));
eventStr = String::Empty(); eventStr = String::Empty();
} }
else if (events & UV_RENAME) { else if (events & UV_RENAME) {
Expand Down
3 changes: 1 addition & 2 deletions src/handle_wrap.cc
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ Handle<Value> HandleWrap::Unref(const Arguments& args) {
} }


wrap->unref = true; wrap->unref = true;
uv_unref(uv_default_loop()); uv_unref(NODE_LOOP());


return v8::Undefined(); return v8::Undefined();
} }
Expand Down Expand Up @@ -102,7 +102,6 @@ Handle<Value> HandleWrap::Close(const Arguments& args) {
assert(!wrap->object_.IsEmpty()); assert(!wrap->object_.IsEmpty());
uv_close(wrap->handle__, OnClose); uv_close(wrap->handle__, OnClose);



HandleWrap::Ref(args); HandleWrap::Ref(args);


wrap->StateChange(); wrap->StateChange();
Expand Down
37 changes: 22 additions & 15 deletions src/node.cc
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ static void Idle(uv_idle_t* watcher, int status) {
static void Check(uv_check_t* watcher, int status) { static void Check(uv_check_t* watcher, int status) {
assert(watcher == &gc_check); assert(watcher == &gc_check);


tick_times[tick_time_head] = uv_now(uv_default_loop()); tick_times[tick_time_head] = uv_now(NODE_LOOP());
tick_time_head = (tick_time_head + 1) % RPM_SAMPLES; tick_time_head = (tick_time_head + 1) % RPM_SAMPLES;


StartGCTimer(); StartGCTimer();
Expand Down Expand Up @@ -200,7 +200,7 @@ static void Tick(void) {
need_tick_cb = false; need_tick_cb = false;
if (uv_is_active((uv_handle_t*) &tick_spinner)) { if (uv_is_active((uv_handle_t*) &tick_spinner)) {
uv_idle_stop(&tick_spinner); uv_idle_stop(&tick_spinner);
uv_unref(uv_default_loop()); uv_unref(NODE_LOOP());
} }


HandleScope scope; HandleScope scope;
Expand Down Expand Up @@ -242,7 +242,7 @@ static Handle<Value> NeedTickCallback(const Arguments& args) {
// tick_spinner to keep the event loop alive long enough to handle it. // tick_spinner to keep the event loop alive long enough to handle it.
if (!uv_is_active((uv_handle_t*) &tick_spinner)) { if (!uv_is_active((uv_handle_t*) &tick_spinner)) {
uv_idle_start(&tick_spinner, Spin); uv_idle_start(&tick_spinner, Spin);
uv_ref(uv_default_loop()); uv_ref(NODE_LOOP());
} }
return Undefined(); return Undefined();
} }
Expand Down Expand Up @@ -1494,7 +1494,7 @@ static void CheckStatus(uv_timer_t* watcher, int status) {
} }
} }


double d = uv_now(uv_default_loop()) - TICK_TIME(3); double d = uv_now(NODE_LOOP()) - TICK_TIME(3);


//printfb("timer d = %f\n", d); //printfb("timer d = %f\n", d);


Expand Down Expand Up @@ -1523,7 +1523,7 @@ static Handle<Value> Uptime(const Arguments& args) {
v8::Handle<v8::Value> UVCounters(const v8::Arguments& args) { v8::Handle<v8::Value> UVCounters(const v8::Arguments& args) {
HandleScope scope; HandleScope scope;


uv_counters_t* c = &uv_default_loop()->counters; uv_counters_t* c = &NODE_LOOP()->counters;


Local<Object> obj = Object::New(); Local<Object> obj = Object::New();


Expand Down Expand Up @@ -2566,26 +2566,29 @@ char** Init(int argc, char *argv[]) {
RegisterSignalHandler(SIGTERM, SignalExit); RegisterSignalHandler(SIGTERM, SignalExit);
#endif // __POSIX__ #endif // __POSIX__


// Don't use NODE_LOOP(), the node::Isolate() has not yet been initialized.
uv_loop_t* const loop = uv_default_loop();

uv_prepare_init(uv_default_loop(), &prepare_tick_watcher); uv_prepare_init(uv_default_loop(), &prepare_tick_watcher);
uv_prepare_start(&prepare_tick_watcher, PrepareTick); uv_prepare_start(&prepare_tick_watcher, PrepareTick);
uv_unref(uv_default_loop()); uv_unref(loop);


uv_check_init(uv_default_loop(), &check_tick_watcher); uv_check_init(uv_default_loop(), &check_tick_watcher);
uv_check_start(&check_tick_watcher, node::CheckTick); uv_check_start(&check_tick_watcher, node::CheckTick);
uv_unref(uv_default_loop()); uv_unref(loop);


uv_idle_init(uv_default_loop(), &tick_spinner); uv_idle_init(uv_default_loop(), &tick_spinner);
uv_unref(uv_default_loop()); uv_unref(loop);


uv_check_init(uv_default_loop(), &gc_check); uv_check_init(uv_default_loop(), &gc_check);
uv_check_start(&gc_check, node::Check); uv_check_start(&gc_check, node::Check);
uv_unref(uv_default_loop()); uv_unref(loop);


uv_idle_init(uv_default_loop(), &gc_idle); uv_idle_init(uv_default_loop(), &gc_idle);
uv_unref(uv_default_loop()); uv_unref(loop);


uv_timer_init(uv_default_loop(), &gc_timer); uv_timer_init(uv_default_loop(), &gc_timer);
uv_unref(uv_default_loop()); uv_unref(loop);


V8::SetFatalErrorHandler(node::OnFatalError); V8::SetFatalErrorHandler(node::OnFatalError);


Expand All @@ -2598,13 +2601,13 @@ char** Init(int argc, char *argv[]) {
// main thread to execute a random bit of javascript - which will give V8 // main thread to execute a random bit of javascript - which will give V8
// control so it can handle whatever new message had been received on the // control so it can handle whatever new message had been received on the
// debug thread. // debug thread.
uv_async_init(uv_default_loop(), &debug_watcher, node::DebugMessageCallback); uv_async_init(loop, &debug_watcher, node::DebugMessageCallback);
// unref it so that we exit the event loop despite it being active. // unref it so that we exit the event loop despite it being active.
uv_unref(uv_default_loop()); uv_unref(loop);


// Fetch a reference to the main isolate, so we have a reference to it // Fetch a reference to the main isolate, so we have a reference to it
// even when we need it to access it from another (debugger) thread. // even when we need it to access it from another (debugger) thread.
node_isolate = Isolate::GetCurrent(); node_isolate = v8::Isolate::GetCurrent();


// If the --debug flag was specified then initialize the debug thread. // If the --debug flag was specified then initialize the debug thread.
if (use_debug_agent) { if (use_debug_agent) {
Expand Down Expand Up @@ -2646,7 +2649,11 @@ int Start(int argc, char *argv[]) {
Persistent<v8::Context> context = v8::Context::New(); Persistent<v8::Context> context = v8::Context::New();
v8::Context::Scope context_scope(context); v8::Context::Scope context_scope(context);


// Create the main node::Isolate object
Isolate::New(uv_default_loop());

Handle<Object> process_l = SetupProcessObject(argc, argv); Handle<Object> process_l = SetupProcessObject(argc, argv);

v8_typed_array::AttachBindings(context->Global()); v8_typed_array::AttachBindings(context->Global());


// Create all the objects, load modules, do everything. // Create all the objects, load modules, do everything.
Expand All @@ -2658,7 +2665,7 @@ int Start(int argc, char *argv[]) {
// there are no watchers on the loop (except for the ones that were // there are no watchers on the loop (except for the ones that were
// uv_unref'd) then this function exits. As long as there are active // uv_unref'd) then this function exits. As long as there are active
// watchers, it blocks. // watchers, it blocks.
uv_run(uv_default_loop()); uv_run(NODE_LOOP());


EmitExit(process_l); EmitExit(process_l);


Expand Down
3 changes: 3 additions & 0 deletions src/node.h
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <assert.h> #include <assert.h>


#include <node_isolate.h>
#include <node_object_wrap.h> #include <node_object_wrap.h>


#ifndef offset_of #ifndef offset_of
Expand All @@ -87,6 +88,8 @@
#define NODE_STRINGIFY_HELPER(n) #n #define NODE_STRINGIFY_HELPER(n) #n
#endif #endif


#define NODE_LOOP() (node::Isolate::GetCurrent()->GetLoop())

namespace node { namespace node {


int Start(int argc, char *argv[]); int Start(int argc, char *argv[]);
Expand Down
5 changes: 3 additions & 2 deletions src/node_crypto.cc
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -4117,7 +4117,8 @@ PBKDF2(const Arguments& args) {


req = new uv_work_t(); req = new uv_work_t();
req->data = request; req->data = request;
uv_queue_work(uv_default_loop(), req, EIO_PBKDF2, EIO_PBKDF2After); uv_queue_work(NODE_LOOP(), req, EIO_PBKDF2, EIO_PBKDF2After);

return Undefined(); return Undefined();


err: err:
Expand Down Expand Up @@ -4239,7 +4240,7 @@ Handle<Value> RandomBytes(const Arguments& args) {
Local<Function> callback_v = Local<Function>(Function::Cast(*args[1])); Local<Function> callback_v = Local<Function>(Function::Cast(*args[1]));
req->callback_ = Persistent<Function>::New(callback_v); req->callback_ = Persistent<Function>::New(callback_v);


uv_queue_work(uv_default_loop(), uv_queue_work(NODE_LOOP(),
&req->work_req_, &req->work_req_,
RandomBytesWork<generator>, RandomBytesWork<generator>,
RandomBytesAfter<generator>); RandomBytesAfter<generator>);
Expand Down
42 changes: 42 additions & 0 deletions src/node_isolate.cc
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// 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_isolate.h"
#include <assert.h>


namespace node {


Isolate* Isolate::New(uv_loop_t* loop) {
return new Isolate(loop);
}


Isolate::Isolate(uv_loop_t* loop) {
loop_ = loop;
isolate_ = v8::Isolate::GetCurrent();
assert(isolate_->GetData() == NULL);
isolate_->SetData(this);
}


} // namespace node
69 changes: 69 additions & 0 deletions src/node_isolate.h
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,69 @@
// Copyright Joyent, Inc. and other Node contributors.
//
// 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 SRC_NODE_ISOLATE_H_
#define SRC_NODE_ISOLATE_H_

#include <v8.h>
#include <uv.h>

#ifdef NDEBUG
# define NODE_ISOLATE_CHECK(ptr) ((void) (ptr))
#else
# include <assert.h>
# define NODE_ISOLATE_CHECK(ptr) \
do { \
node::Isolate* data_ = node::Isolate::GetCurrent(); \
assert(data_ == (ptr)); \
} \
while (0)
#endif


namespace node {

class Isolate {
public:
static Isolate* New(uv_loop_t* loop);

static Isolate* GetCurrent() {
return reinterpret_cast<Isolate*>(v8::Isolate::GetCurrent()->GetData());
}

uv_loop_t* GetLoop() {
NODE_ISOLATE_CHECK(this);
return loop_;
}

operator v8::Isolate*() {
NODE_ISOLATE_CHECK(this);
return isolate_;
}

private:
Isolate(uv_loop_t* loop);
v8::Isolate* isolate_;
uv_loop_t* loop_;
};

} // namespace node

#endif // SRC_NODE_ISOLATE_H_
2 changes: 1 addition & 1 deletion src/node_zlib.cc
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -133,7 +133,7 @@ template <node_zlib_mode mode> class ZCtx : public ObjectWrap {
uv_work_t* work_req = new uv_work_t(); uv_work_t* work_req = new uv_work_t();
work_req->data = req_wrap; work_req->data = req_wrap;


uv_queue_work(uv_default_loop(), uv_queue_work(NODE_LOOP(),
work_req, work_req,
ZCtx<mode>::Process, ZCtx<mode>::Process,
ZCtx<mode>::After); ZCtx<mode>::After);
Expand Down
Loading

0 comments on commit 356992f

Please sign in to comment.