Chromium Code Reviews| Index: samples/shell.cc |
| diff --git a/samples/shell.cc b/samples/shell.cc |
| index 1a13f5f80bff11979c5fdf55cbdebc888ca36825..a4475912fe70c46cee4632ec51ecb719c611837b 100644 |
| --- a/samples/shell.cc |
| +++ b/samples/shell.cc |
| @@ -31,7 +31,14 @@ |
| #include <stdio.h> |
| #include <stdlib.h> |
| +// TODO(isolates): |
| +// o Add thread implementation for more platforms. |
| +// o Do not assume not WIN32 implies pthreads. |
| +#ifndef WIN32 |
| +#include <pthread.h> |
| +#endif |
| +v8::Handle<v8::Context> CreateShellContext(); |
| void RunShell(v8::Handle<v8::Context> context); |
| bool ExecuteString(v8::Handle<v8::String> source, |
| v8::Handle<v8::Value> name, |
| @@ -46,30 +53,123 @@ v8::Handle<v8::String> ReadFile(const char* name); |
| void ReportException(v8::TryCatch* handler); |
| +#ifndef WIN32 |
| +void* IsolateThreadEntry(void* arg); |
| +#endif |
| + |
| +class SourceGroup { |
| + public: |
| + SourceGroup() : argv_(NULL), begin_offset_(0), end_offset_(0) { |
| +#ifndef WIN32 |
| + thread_ = 0; |
| +#endif |
| + } |
| + |
| + void Begin(char** argv, int offset) { |
| + argv_ = const_cast<const char**>(argv); |
| + begin_offset_ = offset; |
| + } |
| + |
| + void End(int offset) { end_offset_ = offset; } |
| + |
| + void Execute() { |
| + for (int i = begin_offset_; i < end_offset_; ++i) { |
| + const char* arg = argv_[i]; |
| + if (strcmp(arg, "-e") == 0 && i + 1 < end_offset_) { |
| + // Execute argument given to -e option directly. |
| + v8::HandleScope handle_scope; |
| + v8::Handle<v8::String> file_name = v8::String::New("unnamed"); |
| + v8::Handle<v8::String> source = v8::String::New(argv_[i + 1]); |
| + if (!ExecuteString(source, file_name, false, true)) { |
| + exit(1); |
| + return; |
| + } |
| + ++i; |
| + } else if (arg[0] == '-') { |
| + // Ignore other options. They have been parsed already. |
| + } else { |
| + // Use all other arguments as names of files to load and run. |
| + v8::HandleScope handle_scope; |
| + v8::Handle<v8::String> file_name = v8::String::New(arg); |
| + v8::Handle<v8::String> source = ReadFile(arg); |
| + if (source.IsEmpty()) { |
| + printf("Error reading '%s'\n", arg); |
| + } |
| + if (!ExecuteString(source, file_name, false, true)) { |
|
yurys
2010/10/06 14:52:58
This code can be extracted out of the if/else expr
|
| + exit(1); |
| + return; |
| + } |
| + } |
| + } |
| + } |
| + |
| +#ifdef WIN32 |
| + void StartExecuteInThread() { ExecuteInThread(); } |
| + void WaitForThread() {} |
| + |
| +#else |
| + void StartExecuteInThread() { |
| + pthread_create(&thread_, NULL, &IsolateThreadEntry, this); |
| + } |
| + |
| + void WaitForThread() { |
| + if (thread_ == 0) return; |
| + pthread_join(thread_, NULL); |
| + thread_ = 0; |
| + } |
| +#endif // WIN32 |
| + |
| + private: |
| + void ExecuteInThread() { |
| + v8::Isolate* isolate = v8::Isolate::New(); |
| + { |
| + v8::Isolate::Scope iscope(isolate); |
| + v8::HandleScope scope; |
| + v8::Context::Scope cscope(CreateShellContext()); |
| + Execute(); |
| + } |
| + isolate->Dispose(); |
| + } |
| + |
| + const char** argv_; |
| + int begin_offset_; |
| + int end_offset_; |
| +#ifndef WIN32 |
| + pthread_t thread_; |
| +#endif |
| + |
| + friend void* IsolateThreadEntry(void* arg); |
| +}; |
| + |
| +#ifndef WIN32 |
| +void* IsolateThreadEntry(void* arg) { |
|
yurys
2010/10/06 14:52:58
This function can be made a private static method
|
| + reinterpret_cast<SourceGroup*>(arg)->ExecuteInThread(); |
| + return NULL; |
| +} |
| +#endif |
| + |
| + |
| int RunMain(int argc, char* argv[]) { |
| v8::V8::SetFlagsFromCommandLine(&argc, argv, true); |
| v8::HandleScope handle_scope; |
| - // Create a template for the global object. |
| - v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(); |
| - // Bind the global 'print' function to the C++ Print callback. |
| - global->Set(v8::String::New("print"), v8::FunctionTemplate::New(Print)); |
| - // Bind the global 'read' function to the C++ Read callback. |
| - global->Set(v8::String::New("read"), v8::FunctionTemplate::New(Read)); |
| - // Bind the global 'load' function to the C++ Load callback. |
| - global->Set(v8::String::New("load"), v8::FunctionTemplate::New(Load)); |
| - // Bind the 'quit' function |
| - global->Set(v8::String::New("quit"), v8::FunctionTemplate::New(Quit)); |
| - // Bind the 'version' function |
| - global->Set(v8::String::New("version"), v8::FunctionTemplate::New(Version)); |
| - // Create a new execution environment containing the built-in |
| - // functions |
| - v8::Handle<v8::Context> context = v8::Context::New(NULL, global); |
| + v8::Handle<v8::Context> context = CreateShellContext(); |
| // Enter the newly created execution environment. |
| v8::Context::Scope context_scope(context); |
| bool run_shell = (argc == 1); |
| + int num_isolates = 1; |
| + for (int i = 1; i < argc; i++) { |
| + if (strcmp(argv[i], "--isolate") == 0) ++num_isolates; |
| + } |
| + SourceGroup* isolate_sources = new SourceGroup[num_isolates]; |
| + SourceGroup* current = isolate_sources; |
| + current->Begin(argv, 1); |
| for (int i = 1; i < argc; i++) { |
| const char* str = argv[i]; |
| - if (strcmp(str, "--shell") == 0) { |
| + if (strcmp(str, "--isolate") == 0) { |
| + current->End(i); |
| + current++; |
| + current->Begin(argv, i + 1); |
| + } else if (strcmp(str, "--shell") == 0) { |
| run_shell = true; |
| } else if (strcmp(str, "-f") == 0) { |
| // Ignore any -f flags for compatibility with the other stand- |
| @@ -77,28 +177,17 @@ int RunMain(int argc, char* argv[]) { |
| continue; |
| } else if (strncmp(str, "--", 2) == 0) { |
| printf("Warning: unknown flag %s.\nTry --help for options\n", str); |
| - } else if (strcmp(str, "-e") == 0 && i + 1 < argc) { |
| - // Execute argument given to -e option directly |
| - v8::HandleScope handle_scope; |
| - v8::Handle<v8::String> file_name = v8::String::New("unnamed"); |
| - v8::Handle<v8::String> source = v8::String::New(argv[i + 1]); |
| - if (!ExecuteString(source, file_name, false, true)) |
| - return 1; |
| - i++; |
| - } else { |
| - // Use all other arguments as names of files to load and run. |
| - v8::HandleScope handle_scope; |
| - v8::Handle<v8::String> file_name = v8::String::New(str); |
| - v8::Handle<v8::String> source = ReadFile(str); |
| - if (source.IsEmpty()) { |
| - printf("Error reading '%s'\n", str); |
| - return 1; |
| - } |
| - if (!ExecuteString(source, file_name, false, true)) |
| - return 1; |
| } |
| } |
| + current->End(argc); |
| + for (int i = 1; i < num_isolates; ++i) { |
| + isolate_sources[i].StartExecuteInThread(); |
| + } |
| + isolate_sources[0].Execute(); |
| if (run_shell) RunShell(context); |
| + for (int i = 1; i < num_isolates; ++i) { |
| + isolate_sources[i].WaitForThread(); |
| + } |
|
yurys
2010/10/06 14:52:58
Should we delete isolate_sources before exit here?
|
| return 0; |
| } |
| @@ -116,6 +205,25 @@ const char* ToCString(const v8::String::Utf8Value& value) { |
| } |
| +// Creates a new execution environment containing the built-in |
| +// functions. |
| +v8::Handle<v8::Context> CreateShellContext() { |
| + // Create a template for the global object. |
| + v8::Handle<v8::ObjectTemplate> global = v8::ObjectTemplate::New(); |
| + // Bind the global 'print' function to the C++ Print callback. |
| + global->Set(v8::String::New("print"), v8::FunctionTemplate::New(Print)); |
| + // Bind the global 'read' function to the C++ Read callback. |
| + global->Set(v8::String::New("read"), v8::FunctionTemplate::New(Read)); |
| + // Bind the global 'load' function to the C++ Load callback. |
| + global->Set(v8::String::New("load"), v8::FunctionTemplate::New(Load)); |
| + // Bind the 'quit' function |
| + global->Set(v8::String::New("quit"), v8::FunctionTemplate::New(Quit)); |
| + // Bind the 'version' function |
| + global->Set(v8::String::New("version"), v8::FunctionTemplate::New(Version)); |
| + return v8::Context::New(NULL, global); |
| +} |
| + |
| + |
| // The callback that is invoked by v8 whenever the JavaScript 'print' |
| // function is called. Prints its arguments on stdout separated by |
| // spaces and ending with a newline. |