Browse Source

Provide task runner for the node mode

Cheng Zhao 9 years ago
parent
commit
599e9b90bb

+ 3 - 0
atom/app/atom_main.cc

@@ -33,6 +33,7 @@
 
 #include "atom/app/node_main.h"
 #include "atom/common/atom_command_line.h"
+#include "base/at_exit.h"
 #include "base/i18n/icu_util.h"
 
 #if defined(OS_WIN)
@@ -134,6 +135,7 @@ int APIENTRY wWinMain(HINSTANCE instance, HINSTANCE, wchar_t* cmd, int) {
   if (env->GetVar("ATOM_SHELL_INTERNAL_RUN_AS_NODE", &node_indicator) &&
       node_indicator == "1") {
     // Now that argv conversion is done, we can finally start.
+    base::AtExitManager atexit_manager;
     base::i18n::InitializeICU();
     return atom::NodeMain(argc, argv);
   } else if (env->GetVar("ATOM_SHELL_INTERNAL_CRASH_SERVICE",
@@ -165,6 +167,7 @@ int main(int argc, const char* argv[]) {
   char* node_indicator = getenv("ATOM_SHELL_INTERNAL_RUN_AS_NODE");
   if (node_indicator != NULL && strcmp(node_indicator, "1") == 0) {
     base::i18n::InitializeICU();
+    base::AtExitManager atexit_manager;
     return atom::NodeMain(argc, const_cast<char**>(argv));
   }
 

+ 9 - 1
atom/app/node_main.cc

@@ -4,10 +4,12 @@
 
 #include "atom/app/node_main.h"
 
+#include "atom/app/uv_task_runner.h"
 #include "atom/browser/javascript_environment.h"
 #include "atom/browser/node_debugger.h"
 #include "atom/common/node_includes.h"
 #include "base/command_line.h"
+#include "base/thread_task_runner_handle.h"
 #include "gin/array_buffer.h"
 #include "gin/public/isolate_holder.h"
 #include "gin/v8_initializer.h"
@@ -24,14 +26,20 @@ int NodeMain(int argc, char *argv[]) {
 
   int exit_code = 1;
   {
+    // Feed gin::PerIsolateData with a task runner.
+    uv_loop_t* loop = uv_default_loop();
+    scoped_refptr<UvTaskRunner> uv_task_runner(new UvTaskRunner(loop));
+    base::ThreadTaskRunnerHandle handle(uv_task_runner);
+
     gin::V8Initializer::LoadV8Snapshot();
+    gin::V8Initializer::LoadV8Natives();
     gin::IsolateHolder::Initialize(
         gin::IsolateHolder::kNonStrictMode,
         gin::ArrayBufferAllocator::SharedInstance());
 
     JavascriptEnvironment gin_env;
     node::Environment* env = node::CreateEnvironment(
-        gin_env.isolate(), uv_default_loop(), gin_env.context(), argc, argv,
+        gin_env.isolate(), loop, gin_env.context(), argc, argv,
         exec_argc, exec_argv);
 
     // Start our custom debugger implementation.

+ 55 - 0
atom/app/uv_task_runner.cc

@@ -0,0 +1,55 @@
+// Copyright (c) 2015 GitHub, Inc.
+// Use of this source code is governed by the MIT license that can be
+// found in the LICENSE file.
+
+#include "atom/app/uv_task_runner.h"
+
+#include "base/stl_util.h"
+
+namespace atom {
+
+UvTaskRunner::UvTaskRunner(uv_loop_t* loop) : loop_(loop) {
+}
+
+UvTaskRunner::~UvTaskRunner() {
+  for (auto& iter : tasks_) {
+    uv_unref(reinterpret_cast<uv_handle_t*>(iter.first));
+    delete iter.first;
+  }
+}
+
+bool UvTaskRunner::PostDelayedTask(const tracked_objects::Location& from_here,
+                                   const base::Closure& task,
+                                   base::TimeDelta delay) {
+  uv_timer_t* timer = new uv_timer_t;
+  timer->data = this;
+  uv_timer_init(loop_, timer);
+  uv_timer_start(timer, UvTaskRunner::OnTimeout, delay.InMilliseconds(), 0);
+  tasks_[timer] = task;
+  return true;
+}
+
+bool UvTaskRunner::RunsTasksOnCurrentThread() const {
+  return true;
+}
+
+bool UvTaskRunner::PostNonNestableDelayedTask(
+    const tracked_objects::Location& from_here,
+    const base::Closure& task,
+    base::TimeDelta delay) {
+  return PostDelayedTask(from_here, task, delay);;
+}
+
+// static
+void UvTaskRunner::OnTimeout(uv_timer_t* timer) {
+  UvTaskRunner* self = static_cast<UvTaskRunner*>(timer->data);
+  if (!ContainsKey(self->tasks_, timer))
+    return;
+
+  self->tasks_[timer].Run();
+  self->tasks_.erase(timer);
+  uv_unref(reinterpret_cast<uv_handle_t*>(timer));
+  delete timer;
+}
+
+}  // namespace atom

+ 44 - 0
atom/app/uv_task_runner.h

@@ -0,0 +1,44 @@
+// Copyright (c) 2015 GitHub, Inc.
+// Use of this source code is governed by the MIT license that can be
+// found in the LICENSE file.
+
+#ifndef ATOM_APP_UV_TASK_RUNNER_H_
+#define ATOM_APP_UV_TASK_RUNNER_H_
+
+#include <map>
+
+#include "base/callback.h"
+#include "base/single_thread_task_runner.h"
+#include "vendor/node/deps/uv/include/uv.h"
+
+namespace atom {
+
+// TaskRunner implementation that posts tasks into libuv's default loop.
+class UvTaskRunner : public base::SingleThreadTaskRunner {
+ public:
+  explicit UvTaskRunner(uv_loop_t* loop);
+  ~UvTaskRunner() override;
+
+  // base::SingleThreadTaskRunner:
+  bool PostDelayedTask(const tracked_objects::Location& from_here,
+                       const base::Closure& task,
+                       base::TimeDelta delay) override;
+  bool RunsTasksOnCurrentThread() const override;
+  bool PostNonNestableDelayedTask(
+      const tracked_objects::Location& from_here,
+      const base::Closure& task,
+      base::TimeDelta delay) override;
+
+ private:
+  static void OnTimeout(uv_timer_t* timer);
+
+  uv_loop_t* loop_;
+
+  std::map<uv_timer_t*, base::Closure> tasks_;
+
+  DISALLOW_COPY_AND_ASSIGN(UvTaskRunner);
+};
+
+}  // namespace atom
+
+#endif  // ATOM_APP_UV_TASK_RUNNER_H_

+ 1 - 1
atom/browser/bridge_task_runner.h

@@ -14,7 +14,7 @@ namespace atom {
 class BridgeTaskRunner : public base::SingleThreadTaskRunner {
  public:
   BridgeTaskRunner() {}
-  ~BridgeTaskRunner() {}
+  ~BridgeTaskRunner() override {}
 
   // base::SingleThreadTaskRunner:
   bool PostDelayedTask(const tracked_objects::Location& from_here,

+ 2 - 0
filenames.gypi

@@ -62,6 +62,8 @@
       'atom/app/atom_main_delegate_mac.mm',
       'atom/app/node_main.cc',
       'atom/app/node_main.h',
+      'atom/app/uv_task_runner.cc',
+      'atom/app/uv_task_runner.h',
       'atom/browser/api/atom_api_app.cc',
       'atom/browser/api/atom_api_app.h',
       'atom/browser/api/atom_api_auto_updater.cc',