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
  • Loading branch information
ry committed Dec 18, 2011
1 parent c04f0f9 commit db6d846
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 39 deletions.
1 change: 1 addition & 0 deletions deps/uv/include/uv.h
Expand Up @@ -1342,6 +1342,7 @@ UV_EXTERN void uv_rwlock_wrunlock(uv_rwlock_t* rwlock);
UV_EXTERN int uv_thread_create(uv_thread_t *tid,
void (*entry)(void *arg), void *arg);
UV_EXTERN int uv_thread_join(uv_thread_t *tid);
UV_EXTERN uv_thread_t uv_thread_self(void);

/* the presence of these unions force similar struct layout */
union uv_any_handle {
Expand Down
4 changes: 4 additions & 0 deletions deps/uv/src/unix/thread.c
Expand Up @@ -47,6 +47,10 @@ int uv_thread_join(uv_thread_t *tid) {
return 0;
}

uv_thread_t uv_thread_self(void) {
return pthread_self();
}


int uv_mutex_init(uv_mutex_t* mutex) {
if (pthread_mutex_init(mutex, NULL))
Expand Down
58 changes: 32 additions & 26 deletions src/node.cc
Expand Up @@ -1867,16 +1867,6 @@ struct ThreadInfo {
}

ThreadInfo(Handle<Array> args) {
argc_ = args->Length();
argv_ = new char*[argc_ + 1];

for (int i = 0; i < argc_; ++i) {
String::Utf8Value str(args->Get(i));
size_t size = 1 + strlen(*str);
argv_[i] = new char[size];
memcpy(argv_[i], *str, size);
}
argv_[argc_] = NULL;
}

~ThreadInfo() {
Expand All @@ -1889,14 +1879,8 @@ struct ThreadInfo {


static void RunIsolate(void* arg) {
ThreadInfo* ti = reinterpret_cast<ThreadInfo*>(arg);

Isolate* isolate = Isolate::New();

StartThread(isolate, ti->argc_, ti->argv_);
isolate->Dispose();

delete ti;
node::Isolate* isolate = reinterpret_cast<node::Isolate*>(arg);
StartThread(isolate, isolate->argc_, isolate->argv_);
delete isolate;
}

Expand All @@ -1912,10 +1896,23 @@ static Handle<Value> NewIsolate(const Arguments& args) {
Local<Array> argv = args[0].As<Array>();
assert(argv->Length() >= 2);

ThreadInfo* ti = new ThreadInfo(argv);
// Note that isolate lock is aquired in the constructor here. It will not
// be unlocked until RunIsolate starts and calls isolate->Enter().
Isolate* isolate = new node::Isolate();

// Copy over arguments into isolate
isolate->argc_ = argv->Length();
isolate->argv_ = new char*[isolate->argc_ + 1];
for (int i = 0; i < isolate->argc_; ++i) {
String::Utf8Value str(argv->Get(i));
size_t size = 1 + strlen(*str);
isolate->argv_[i] = new char[size];
memcpy(isolate->argv_[i], *str, size);
}
isolate->argv_[isolate->argc_] = NULL;

if (uv_thread_create(&ti->thread_, RunIsolate, ti)) {
delete ti;
if (uv_thread_create(&isolate->tid_, RunIsolate, isolate)) {
delete isolate;
return Null();
}

Expand All @@ -1924,7 +1921,7 @@ static Handle<Value> NewIsolate(const Arguments& args) {

Local<Object> obj = tpl->NewInstance();
obj->SetPointerInInternalField(0, magic_isolate_cookie_);
obj->SetPointerInInternalField(1, ti);
obj->SetPointerInInternalField(1, isolate);

return scope.Close(obj);
}
Expand Down Expand Up @@ -2692,8 +2689,7 @@ void StartThread(node::Isolate* isolate,
char** argv) {
HandleScope scope;

v8::Isolate::Scope isolate_scope(isolate->GetV8Isolate());
v8::Context::Scope context_scope(isolate->GetV8Context());
isolate->Enter();

uv_loop_t* loop = isolate->GetLoop();
uv_prepare_init(loop, &prepare_tick_watcher);
Expand Down Expand Up @@ -2769,6 +2765,9 @@ void StartThread(node::Isolate* isolate,
uv_run(loop);

EmitExit(process_l);

isolate->Exit();
isolate->Dispose();
}


Expand All @@ -2779,11 +2778,18 @@ int Start(int argc, char *argv[]) {
v8::V8::Initialize();
v8::HandleScope handle_scope;

// Get the id of the this, the main, thread.
uv_thread_t tid = uv_thread_self();

// Create the main node::Isolate object
node::Isolate::Initialize();
Isolate* isolate = node::Isolate::New();
Isolate* isolate = new node::Isolate();
isolate->tid_ = tid;
StartThread(isolate, argc, argv);
isolate->Dispose();

// The main thread/isolate is done. Wait for all other thread/isolates to
// finish.
node::Isolate::JoinAll();

#ifndef NDEBUG
// Clean up.
Expand Down
49 changes: 38 additions & 11 deletions src/node_isolate.cc
Expand Up @@ -46,17 +46,37 @@ void Isolate::Initialize() {
}


Isolate* Isolate::New() {
return new Isolate();
int Isolate::Count() {
return isolate_count;
}


int Isolate::Count() {
return isolate_count;
void Isolate::JoinAll() {
uv_mutex_lock(&list_lock);

while (ngx_queue_empty(&list_head) == false) {
ngx_queue_t* q = ngx_queue_head(&list_head);
Isolate* isolate = ngx_queue_data(q, Isolate, list_member_);

// Unlock the list while we join the thread.
uv_mutex_unlock(&list_lock);

uv_thread_join(&isolate->tid_);
printf("join isolate %d\n", isolate->id_);

// Relock to check the next element in the list.
uv_mutex_lock(&list_lock);
}

// Unlock the list finally.
uv_mutex_unlock(&list_lock);
}


Isolate::Isolate() {
uv_mutex_init(&lock_);
uv_mutex_lock(&lock_);

uv_mutex_lock(&list_lock);

assert(initialized && "node::Isolate::Initialize() hasn't been called");
Expand All @@ -79,19 +99,15 @@ Isolate::Isolate() {

uv_mutex_unlock(&list_lock);

v8_isolate_ = v8::Isolate::GetCurrent();
if (v8_isolate_ == NULL) {
v8_isolate_ = v8::Isolate::New();
v8_isolate_->Enter();
}

v8_isolate_ = v8::Isolate::New();
assert(v8_isolate_->GetData() == NULL);
v8_isolate_->SetData(this);

v8_context_ = v8::Context::New();
v8_context_->Enter();

Enter();
globals_init(&globals_);
Exit();
}


Expand All @@ -112,6 +128,17 @@ void Isolate::AtExit(AtExitCallback callback, void* arg) {
}


void Isolate::Enter() {
v8_isolate_->Enter();
v8_context_->Enter();
}

void Isolate::Exit() {
v8_context_->Exit();
v8_isolate_->Exit();
}


void Isolate::Dispose() {
uv_mutex_lock(&list_lock);

Expand Down
24 changes: 22 additions & 2 deletions src/node_isolate.h
Expand Up @@ -43,13 +43,17 @@ namespace node {

class Isolate {
public:
char** argv_;
int argc_;
uv_thread_t tid_;

// Call this before instantiating any Isolate
static void Initialize();
static int Count();

typedef void (*AtExitCallback)(void* arg);

static Isolate* New();
static void JoinAll();

static Isolate* GetCurrent() {
return reinterpret_cast<Isolate*>(v8::Isolate::GetCurrent()->GetData());
Expand Down Expand Up @@ -82,9 +86,20 @@ class Isolate {

unsigned int id_;

private:
// This constructor is used for every non-main thread
Isolate();

~Isolate() {
if (argv_) {
delete argv_;
}
}

void Enter();
void Exit();

private:

struct AtExitCallbackInfo {
ngx_queue_t at_exit_callbacks_;
AtExitCallback callback_;
Expand All @@ -101,6 +116,11 @@ class Isolate {

// Global variables for this isolate.
struct globals globals_;

// This is used to lock the isolate while the new thread boots. If anyone
// calls isolate->join() before then - it will wait until the thread has
// started.
uv_mutex_t lock_;
};

} // namespace node
Expand Down

0 comments on commit db6d846

Please sign in to comment.