diff --git a/src/node.cc b/src/node.cc index 548fdc7b3dc..4cedfbc0186 100644 --- a/src/node.cc +++ b/src/node.cc @@ -21,6 +21,7 @@ #include #include +#include #include @@ -142,10 +143,6 @@ static bool print_eval; static void CheckStatus(uv_timer_t* watcher, int status); -void StartThread(Isolate* isolate, - int argc, - char** argv); - uv_loop_t* Loop() { #if defined(HAVE_ISOLATES) && HAVE_ISOLATES @@ -1859,82 +1856,6 @@ static Handle Binding(const Arguments& args) { } -static void RunIsolate(void* arg) { - node::Isolate* isolate = reinterpret_cast(arg); - isolate->Enter(); - StartThread(isolate, isolate->argc_, isolate->argv_); - isolate->Dispose(); - delete isolate; -} - - -static char magic_isolate_cookie_[] = "magic isolate cookie"; - - -static Handle NewIsolate(const Arguments& args) { - HandleScope scope; - - assert(args[0]->IsArray()); - - Local argv = args[0].As(); - assert(argv->Length() >= 2); - - // 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(&isolate->tid_, RunIsolate, isolate)) { - delete isolate; - return Null(); - } - - Local tpl = ObjectTemplate::New(); - tpl->SetInternalFieldCount(2); - - Local obj = tpl->NewInstance(); - obj->SetPointerInInternalField(0, magic_isolate_cookie_); - obj->SetPointerInInternalField(1, isolate); - - return scope.Close(obj); -} - - -static Handle CountIsolate(const Arguments& args) { - HandleScope scope; - return scope.Close(Integer::New(Isolate::Count())); -} - - -static Handle JoinIsolate(const Arguments& args) { - HandleScope scope; - - assert(args[0]->IsObject()); - - Local obj = args[0]->ToObject(); - assert(obj->InternalFieldCount() == 2); - assert(obj->GetPointerFromInternalField(0) == magic_isolate_cookie_); - - Isolate* ti = reinterpret_cast( - obj->GetPointerFromInternalField(1)); - - if (uv_thread_join(&ti->tid_)) - return False(); // error - else - return True(); // ok -} - - static Handle ProcessTitleGetter(Local property, const AccessorInfo& info) { HandleScope scope; @@ -2206,10 +2127,6 @@ Handle SetupProcessObject(int argc, char *argv[]) { NODE_SET_METHOD(process, "binding", Binding); - NODE_SET_METHOD(process, "_newIsolate", NewIsolate); - NODE_SET_METHOD(process, "_countIsolate", CountIsolate); - NODE_SET_METHOD(process, "_joinIsolate", JoinIsolate); - return process; } diff --git a/src/node_extensions.h b/src/node_extensions.h index 39ddf1748fa..1d5b1322386 100644 --- a/src/node_extensions.h +++ b/src/node_extensions.h @@ -34,6 +34,10 @@ NODE_EXT_LIST_ITEM(node_signal_watcher) NODE_EXT_LIST_ITEM(node_os) NODE_EXT_LIST_ITEM(node_zlib) +#if defined(HAVE_ISOLATES) && HAVE_ISOLATES +NODE_EXT_LIST_ITEM(node_isolates) +#endif + // libuv rewrite NODE_EXT_LIST_ITEM(node_timer_wrap) NODE_EXT_LIST_ITEM(node_tcp_wrap) diff --git a/src/node_internals.h b/src/node_internals.h index 8088e229ecb..08dbcb1f439 100644 --- a/src/node_internals.h +++ b/src/node_internals.h @@ -24,6 +24,13 @@ namespace node { +// This function starts an Isolate. This function is defined in node.cc +// currently so that we minimize the diff between master and v0.6 for easy +// merging. In the future, when v0.6 is extinct, StartThread should be moved +// to node_isolate.cc. +class Isolate; +void StartThread(Isolate* isolate, int argc, char** argv); + #ifndef offset_of // g++ in strict mode complains loudly about the system offsetof() macro // because it uses NULL as the base address. diff --git a/src/node_isolate.cc b/src/node_isolate.cc index e2d39222b93..a05cbea3686 100644 --- a/src/node_isolate.cc +++ b/src/node_isolate.cc @@ -19,16 +19,34 @@ // 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 +#include +#include +#include #include #include #include - namespace node { +using v8::Arguments; +using v8::Array; +using v8::False; +using v8::Handle; +using v8::HandleScope; +using v8::Integer; +using v8::Local; +using v8::Null; +using v8::Object; +using v8::ObjectTemplate; +using v8::String; +using v8::True; +using v8::Value; + +static char magic_isolate_cookie_[] = "magic isolate cookie"; + static volatile bool initialized; static volatile int id; @@ -166,4 +184,95 @@ void Isolate::Dispose() { } +static void RunIsolate(void* arg) { + node::Isolate* isolate = reinterpret_cast(arg); + isolate->Enter(); + + // TODO in the future when v0.6 is dead, move StartThread and related + // handles into node_isolate.cc. It is currently organized like this to + // minimize diff (and thus merge conflicts) between the legacy v0.6 + // branch. + StartThread(isolate, isolate->argc_, isolate->argv_); + + isolate->Dispose(); + delete isolate; +} + + +static Handle CreateIsolate(const Arguments& args) { + HandleScope scope; + + assert(args[0]->IsArray()); + + Local argv = args[0].As(); + assert(argv->Length() >= 2); + + // 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(&isolate->tid_, RunIsolate, isolate)) { + delete isolate; + return Null(); + } + + // TODO instead of ObjectTemplate - have a special wrapper. + Local tpl = ObjectTemplate::New(); + tpl->SetInternalFieldCount(2); + + Local obj = tpl->NewInstance(); + obj->SetPointerInInternalField(0, magic_isolate_cookie_); + obj->SetPointerInInternalField(1, isolate); + + return scope.Close(obj); +} + + +static Handle CountIsolate(const Arguments& args) { + HandleScope scope; + return scope.Close(Integer::New(Isolate::Count())); +} + + +static Handle JoinIsolate(const Arguments& args) { + HandleScope scope; + + assert(args[0]->IsObject()); + + Local obj = args[0]->ToObject(); + assert(obj->InternalFieldCount() == 2); + assert(obj->GetPointerFromInternalField(0) == magic_isolate_cookie_); + + Isolate* ti = reinterpret_cast( + obj->GetPointerFromInternalField(1)); + + if (uv_thread_join(&ti->tid_)) + return False(); // error + else + return True(); // ok +} + + +void InitIsolates(Handle target) { + HandleScope scope; + NODE_SET_METHOD(target, "create", CreateIsolate); + NODE_SET_METHOD(target, "count", CountIsolate); + NODE_SET_METHOD(target, "join", JoinIsolate); +} + + } // namespace node + + +NODE_MODULE(node_isolates, node::InitIsolates) diff --git a/test/addons/shared-buffer/test.js b/test/addons/shared-buffer/test.js index ab7da43bd68..9ba896f28a9 100644 --- a/test/addons/shared-buffer/test.js +++ b/test/addons/shared-buffer/test.js @@ -1,10 +1,11 @@ var assert = require('assert'); var binding = require('./out/Release/binding'); +var isolates = process.binding('isolates'); console.log("binding.length =", binding.length); if (process.tid === 1) { - var isolate = process._newIsolate(process.argv); + var isolate = isolates.create(process.argv); for (var i = 0; i < binding.length; i++) { console.log('parent', 'binding.set(' + i + ', ' + i + ')', diff --git a/test/simple/test-isolates.js b/test/simple/test-isolates.js index 810ae95b8d9..fa2dccd3307 100644 --- a/test/simple/test-isolates.js +++ b/test/simple/test-isolates.js @@ -1,10 +1,11 @@ var fs = require('fs'); var http = require('http'); +var isolates = process.binding('isolates'); -console.log("count: %d", process._countIsolate()); +console.log("count: %d", isolates.count()); if (process.tid === 1) { - var isolate = process._newIsolate(process.argv); + var isolate = isolates.create(process.argv); //process._joinIsolate(isolate); console.error("master"); fs.stat(__dirname, function(err, stat) { @@ -19,7 +20,7 @@ if (process.tid === 1) { }); }, 500); - console.log("thread 1 count: %d", process._countIsolate()); + console.log("thread 1 count: %d", isolates.count()); } else { console.error("slave"); fs.stat(__dirname, function(err, stat) { @@ -34,5 +35,5 @@ if (process.tid === 1) { }); }, 500); - console.error("thread 2 count: %d", process._countIsolate()); + console.error("thread 2 count: %d", isolates.count()); }