Skip to content
This repository has been archived by the owner on Apr 22, 2023. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
isolates: isolate-ify the main loop
  • Loading branch information
bnoordhuis committed Nov 22, 2011
1 parent b20a257 commit 9f27c2c
Show file tree
Hide file tree
Showing 18 changed files with 207 additions and 85 deletions.
2 changes: 2 additions & 0 deletions node.gyp
Expand Up @@ -73,6 +73,7 @@
'src/handle_wrap.cc',
'src/node.cc',
'src/node_buffer.cc',
'src/node_isolate.cc',
'src/node_constants.cc',
'src/node_extensions.cc',
'src/node_file.cc',
Expand All @@ -95,6 +96,7 @@
'src/handle_wrap.h',
'src/node.h',
'src/node_buffer.h',
'src/node_isolate.h',
'src/node_constants.h',
'src/node_crypto.h',
'src/node_extensions.h',
Expand Down
8 changes: 4 additions & 4 deletions src/cares_wrap.cc
Expand Up @@ -607,7 +607,7 @@ void AfterGetAddrInfo(uv_getaddrinfo_t* req, int status, struct addrinfo* res) {

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

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

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

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);

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

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) {
// Check for persistent argument
if (!args[1]->IsTrue()) {
uv_unref(uv_default_loop());
uv_unref(NODE_LOOP());
}
wrap->initialized_ = true;
} else {
SetErrno(uv_last_error(uv_default_loop()));
SetErrno(uv_last_error(NODE_LOOP()));
}

return scope.Close(Integer::New(r));
Expand All @@ -134,7 +134,7 @@ void FSEventWrap::OnEvent(uv_fs_event_t* handle, const char* filename,
assert(wrap->object_.IsEmpty() == false);

if (status) {
SetErrno(uv_last_error(uv_default_loop()));
SetErrno(uv_last_error(NODE_LOOP()));
eventStr = String::Empty();
} else {
switch (events) {
Expand Down
4 changes: 2 additions & 2 deletions src/handle_wrap.cc
Expand Up @@ -68,7 +68,7 @@ Handle<Value> HandleWrap::Unref(const Arguments& args) {
assert(wrap->unref == false);

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

return v8::Undefined();
}
Expand All @@ -83,7 +83,7 @@ Handle<Value> HandleWrap::Close(const Arguments& args) {
uv_close(wrap->handle__, OnClose);

if (wrap->unref) {
uv_ref(uv_default_loop());
uv_ref(NODE_LOOP());
wrap->unref = false;
}

Expand Down
50 changes: 28 additions & 22 deletions src/node.cc
Expand Up @@ -193,7 +193,7 @@ static void Idle(uv_idle_t* watcher, int status) {
static void Check(uv_check_t* watcher, int status) {
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;

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

HandleScope scope;
Expand Down Expand Up @@ -265,7 +265,7 @@ static Handle<Value> NeedTickCallback(const Arguments& args) {
// tick_spinner to keep the event loop alive long enough to handle it.
if (!uv_is_active((uv_handle_t*) &tick_spinner)) {
uv_idle_start(&tick_spinner, Spin);
uv_ref(uv_default_loop());
uv_ref(NODE_LOOP());
}
return Undefined();
}
Expand Down Expand Up @@ -1338,7 +1338,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);

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

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

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

Expand Down Expand Up @@ -2109,7 +2109,7 @@ static void ParseArgs(int argc, char **argv) {
}


static Isolate* node_isolate = NULL;
static v8::Isolate* node_isolate = NULL;
static volatile bool debugger_running = false;

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

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

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

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

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

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

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

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

V8::SetFatalErrorHandler(node::OnFatalError);

Expand All @@ -2414,14 +2417,14 @@ char** Init(int argc, char *argv[]) {
// 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
// debug thread.
uv_async_init(uv_default_loop(), &node::debug_watcher,
uv_async_init(loop, &node::debug_watcher,
node::DebugMessageCallback);
// 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
// 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 (node::use_debug_agent) {
Expand Down Expand Up @@ -2463,6 +2466,9 @@ int Start(int argc, char *argv[]) {
Persistent<v8::Context> context = v8::Context::New();
v8::Context::Scope context_scope(context);

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

Handle<Object> process = SetupProcessObject(argc, argv);
v8_typed_array::AttachBindings(context->Global());

Expand All @@ -2475,7 +2481,7 @@ int Start(int argc, char *argv[]) {
// 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
// watchers, it blocks.
uv_run(uv_default_loop());
uv_run(NODE_LOOP());

EmitExit(process);

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

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

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

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

namespace node {

int Start(int argc, char *argv[]);
Expand Down
4 changes: 2 additions & 2 deletions src/node_crypto.cc
Expand Up @@ -4108,7 +4108,7 @@ PBKDF2(const Arguments& args) {

uv_work_t* req = new uv_work_t();
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();
}
Expand Down Expand Up @@ -4225,7 +4225,7 @@ Handle<Value> RandomBytes(const Arguments& args) {
Local<Function> callback_v = Local<Function>(Function::Cast(*args[1]));
req->callback_ = Persistent<Function>::New(callback_v);

uv_queue_work(uv_default_loop(),
uv_queue_work(NODE_LOOP(),
&req->work_req_,
RandomBytesWork<generator>,
RandomBytesAfter<generator>);
Expand Down
6 changes: 3 additions & 3 deletions src/node_file.cc
Expand Up @@ -274,7 +274,7 @@ Local<Value> FSError(int errorno,

#define ASYNC_CALL(func, callback, ...) \
FSReqWrap* req_wrap = new FSReqWrap(); \
int r = uv_fs_##func(uv_default_loop(), &req_wrap->req_, \
int r = uv_fs_##func(NODE_LOOP(), &req_wrap->req_, \
__VA_ARGS__, After); \
assert(r == 0); \
req_wrap->object_->Set(oncomplete_sym, callback); \
Expand All @@ -283,9 +283,9 @@ Local<Value> FSError(int errorno,

#define SYNC_CALL(func, path, ...) \
fs_req_wrap req_wrap; \
int result = uv_fs_##func(uv_default_loop(), &req_wrap.req, __VA_ARGS__, NULL); \
int result = uv_fs_##func(NODE_LOOP(), &req_wrap.req, __VA_ARGS__, NULL); \
if (result < 0) { \
int code = uv_last_error(uv_default_loop()).code; \
int code = uv_last_error(NODE_LOOP()).code; \
return ThrowException(FSError(code, #func, "", path)); \
}

Expand Down
42 changes: 42 additions & 0 deletions src/node_isolate.cc
@@ -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
@@ -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_

0 comments on commit 9f27c2c

Please sign in to comment.