diff options
author | Anna Henningsen <anna@addaleax.net> | 2017-11-19 14:29:08 +0100 |
---|---|---|
committer | James M Snell <jasnell@gmail.com> | 2017-11-21 07:38:03 -0800 |
commit | f005656719326bd68e12cda0c0af78756ebd11c6 (patch) | |
tree | e9f1cce83dc72664d19b0b4bd74a7223fb031541 /src | |
parent | 2540e3dacfe7ae55f4b3f2c229d8486d88a0622c (diff) | |
download | node-new-f005656719326bd68e12cda0c0af78756ebd11c6.tar.gz |
src: implement v8::TaskRunner API in NodePlatform
V8 is switching APIs for scheduling tasks. Implement the new APIs.
Fixes: https://github.com/nodejs/node-v8/issues/24
Refs: https://github.com/v8/v8/commit/c690f54d9580243c53f7d892fcff1ce6bae4bfc0
PR-URL: https://github.com/nodejs/node/pull/17134
Fixes: https://github.com/nodejs/node-v8/issues/24
Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: James M Snell <jasnell@gmail.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/node_platform.cc | 115 | ||||
-rw-r--r-- | src/node_platform.h | 48 |
2 files changed, 119 insertions, 44 deletions
diff --git a/src/node_platform.cc b/src/node_platform.cc index 0c50e8468d..65d1ef6c5d 100644 --- a/src/node_platform.cc +++ b/src/node_platform.cc @@ -24,6 +24,43 @@ static void BackgroundRunner(void* data) { } } +BackgroundTaskRunner::BackgroundTaskRunner(int thread_pool_size) { + for (int i = 0; i < thread_pool_size; i++) { + std::unique_ptr<uv_thread_t> t { new uv_thread_t() }; + if (uv_thread_create(t.get(), BackgroundRunner, &background_tasks_) != 0) + break; + threads_.push_back(std::move(t)); + } +} + +void BackgroundTaskRunner::PostTask(std::unique_ptr<Task> task) { + background_tasks_.Push(std::move(task)); +} + +void BackgroundTaskRunner::PostIdleTask(std::unique_ptr<v8::IdleTask> task) { + UNREACHABLE(); +} + +void BackgroundTaskRunner::PostDelayedTask(std::unique_ptr<v8::Task> task, + double delay_in_seconds) { + UNREACHABLE(); +} + +void BackgroundTaskRunner::BlockingDrain() { + background_tasks_.BlockingDrain(); +} + +void BackgroundTaskRunner::Shutdown() { + background_tasks_.Stop(); + for (size_t i = 0; i < threads_.size(); i++) { + CHECK_EQ(0, uv_thread_join(threads_[i].get())); + } +} + +size_t BackgroundTaskRunner::NumberOfAvailableBackgroundThreads() const { + return threads_.size(); +} + PerIsolatePlatformData::PerIsolatePlatformData( v8::Isolate* isolate, uv_loop_t* loop) : isolate_(isolate), loop_(loop) { @@ -38,17 +75,20 @@ void PerIsolatePlatformData::FlushTasks(uv_async_t* handle) { platform_data->FlushForegroundTasksInternal(); } -void PerIsolatePlatformData::CallOnForegroundThread( - std::unique_ptr<Task> task) { +void PerIsolatePlatformData::PostIdleTask(std::unique_ptr<v8::IdleTask> task) { + UNREACHABLE(); +} + +void PerIsolatePlatformData::PostTask(std::unique_ptr<Task> task) { foreground_tasks_.Push(std::move(task)); uv_async_send(flush_tasks_); } -void PerIsolatePlatformData::CallDelayedOnForegroundThread( - std::unique_ptr<Task> task, double delay_in_seconds) { +void PerIsolatePlatformData::PostDelayedTask( + std::unique_ptr<Task> task, double delay_in_seconds) { std::unique_ptr<DelayedTask> delayed(new DelayedTask()); delayed->task = std::move(task); - delayed->platform_data = this; + delayed->platform_data = shared_from_this(); delayed->timeout = delay_in_seconds; foreground_delayed_tasks_.Push(std::move(delayed)); uv_async_send(flush_tasks_); @@ -80,49 +120,43 @@ NodePlatform::NodePlatform(int thread_pool_size, TracingController* controller = new TracingController(); tracing_controller_.reset(controller); } - for (int i = 0; i < thread_pool_size; i++) { - uv_thread_t* t = new uv_thread_t(); - if (uv_thread_create(t, BackgroundRunner, &background_tasks_) != 0) { - delete t; - break; - } - threads_.push_back(std::unique_ptr<uv_thread_t>(t)); - } + background_task_runner_ = + std::make_shared<BackgroundTaskRunner>(thread_pool_size); } void NodePlatform::RegisterIsolate(IsolateData* isolate_data, uv_loop_t* loop) { Isolate* isolate = isolate_data->isolate(); Mutex::ScopedLock lock(per_isolate_mutex_); - PerIsolatePlatformData* existing = per_isolate_[isolate]; - if (existing != nullptr) + std::shared_ptr<PerIsolatePlatformData> existing = per_isolate_[isolate]; + if (existing) { existing->ref(); - else - per_isolate_[isolate] = new PerIsolatePlatformData(isolate, loop); + } else { + per_isolate_[isolate] = + std::make_shared<PerIsolatePlatformData>(isolate, loop); + } } void NodePlatform::UnregisterIsolate(IsolateData* isolate_data) { Isolate* isolate = isolate_data->isolate(); Mutex::ScopedLock lock(per_isolate_mutex_); - PerIsolatePlatformData* existing = per_isolate_[isolate]; - CHECK_NE(existing, nullptr); + std::shared_ptr<PerIsolatePlatformData> existing = per_isolate_[isolate]; + CHECK(existing); if (existing->unref() == 0) { - delete existing; per_isolate_.erase(isolate); } } void NodePlatform::Shutdown() { - background_tasks_.Stop(); - for (size_t i = 0; i < threads_.size(); i++) { - CHECK_EQ(0, uv_thread_join(threads_[i].get())); + background_task_runner_->Shutdown(); + + { + Mutex::ScopedLock lock(per_isolate_mutex_); + per_isolate_.clear(); } - Mutex::ScopedLock lock(per_isolate_mutex_); - for (const auto& pair : per_isolate_) - delete pair.second; } size_t NodePlatform::NumberOfAvailableBackgroundThreads() { - return threads_.size(); + return background_task_runner_->NumberOfAvailableBackgroundThreads(); } void PerIsolatePlatformData::RunForegroundTask(std::unique_ptr<Task> task) { @@ -155,14 +189,14 @@ void PerIsolatePlatformData::CancelPendingDelayedTasks() { } void NodePlatform::DrainBackgroundTasks(Isolate* isolate) { - PerIsolatePlatformData* per_isolate = ForIsolate(isolate); + std::shared_ptr<PerIsolatePlatformData> per_isolate = ForIsolate(isolate); do { // Right now, there is no way to drain only background tasks associated // with a specific isolate, so this sometimes does more work than // necessary. In the long run, that functionality is probably going to // be available anyway, though. - background_tasks_.BlockingDrain(); + background_task_runner_->BlockingDrain(); } while (per_isolate->FlushForegroundTasksInternal()); } @@ -198,24 +232,25 @@ bool PerIsolatePlatformData::FlushForegroundTasksInternal() { void NodePlatform::CallOnBackgroundThread(Task* task, ExpectedRuntime expected_runtime) { - background_tasks_.Push(std::unique_ptr<Task>(task)); + background_task_runner_->PostTask(std::unique_ptr<Task>(task)); } -PerIsolatePlatformData* NodePlatform::ForIsolate(Isolate* isolate) { +std::shared_ptr<PerIsolatePlatformData> +NodePlatform::ForIsolate(Isolate* isolate) { Mutex::ScopedLock lock(per_isolate_mutex_); - PerIsolatePlatformData* data = per_isolate_[isolate]; - CHECK_NE(data, nullptr); + std::shared_ptr<PerIsolatePlatformData> data = per_isolate_[isolate]; + CHECK(data); return data; } void NodePlatform::CallOnForegroundThread(Isolate* isolate, Task* task) { - ForIsolate(isolate)->CallOnForegroundThread(std::unique_ptr<Task>(task)); + ForIsolate(isolate)->PostTask(std::unique_ptr<Task>(task)); } void NodePlatform::CallDelayedOnForegroundThread(Isolate* isolate, Task* task, double delay_in_seconds) { - ForIsolate(isolate)->CallDelayedOnForegroundThread( + ForIsolate(isolate)->PostDelayedTask( std::unique_ptr<Task>(task), delay_in_seconds); } @@ -229,6 +264,16 @@ void NodePlatform::CancelPendingDelayedTasks(v8::Isolate* isolate) { bool NodePlatform::IdleTasksEnabled(Isolate* isolate) { return false; } +std::shared_ptr<v8::TaskRunner> +NodePlatform::GetBackgroundTaskRunner(Isolate* isolate) { + return background_task_runner_; +} + +std::shared_ptr<v8::TaskRunner> +NodePlatform::GetForegroundTaskRunner(Isolate* isolate) { + return ForIsolate(isolate); +} + double NodePlatform::MonotonicallyIncreasingTime() { // Convert nanos to seconds. return uv_hrtime() / 1e9; diff --git a/src/node_platform.h b/src/node_platform.h index 48301a05a1..e5253cac10 100644 --- a/src/node_platform.h +++ b/src/node_platform.h @@ -43,17 +43,22 @@ struct DelayedTask { std::unique_ptr<v8::Task> task; uv_timer_t timer; double timeout; - PerIsolatePlatformData* platform_data; + std::shared_ptr<PerIsolatePlatformData> platform_data; }; -class PerIsolatePlatformData { +// This acts as the foreground task runner for a given Isolate. +class PerIsolatePlatformData : + public v8::TaskRunner, + public std::enable_shared_from_this<PerIsolatePlatformData> { public: PerIsolatePlatformData(v8::Isolate* isolate, uv_loop_t* loop); ~PerIsolatePlatformData(); - void CallOnForegroundThread(std::unique_ptr<v8::Task> task); - void CallDelayedOnForegroundThread(std::unique_ptr<v8::Task> task, - double delay_in_seconds); + void PostTask(std::unique_ptr<v8::Task> task) override; + void PostIdleTask(std::unique_ptr<v8::IdleTask> task) override; + void PostDelayedTask(std::unique_ptr<v8::Task> task, + double delay_in_seconds) override; + bool IdleTasksEnabled() override { return false; }; void Shutdown(); @@ -84,6 +89,26 @@ class PerIsolatePlatformData { std::vector<DelayedTaskPointer> scheduled_delayed_tasks_; }; +// This acts as the single background task runner for all Isolates. +class BackgroundTaskRunner : public v8::TaskRunner { + public: + explicit BackgroundTaskRunner(int thread_pool_size); + + void PostTask(std::unique_ptr<v8::Task> task) override; + void PostIdleTask(std::unique_ptr<v8::IdleTask> task) override; + void PostDelayedTask(std::unique_ptr<v8::Task> task, + double delay_in_seconds) override; + bool IdleTasksEnabled() override { return false; }; + + void BlockingDrain(); + void Shutdown(); + + size_t NumberOfAvailableBackgroundThreads() const; + private: + TaskQueue<v8::Task> background_tasks_; + std::vector<std::unique_ptr<uv_thread_t>> threads_; +}; + class NodePlatform : public MultiIsolatePlatform { public: NodePlatform(int thread_pool_size, v8::TracingController* tracing_controller); @@ -109,15 +134,20 @@ class NodePlatform : public MultiIsolatePlatform { void RegisterIsolate(IsolateData* isolate_data, uv_loop_t* loop) override; void UnregisterIsolate(IsolateData* isolate_data) override; + std::shared_ptr<v8::TaskRunner> GetBackgroundTaskRunner( + v8::Isolate* isolate) override; + std::shared_ptr<v8::TaskRunner> GetForegroundTaskRunner( + v8::Isolate* isolate) override; + private: - PerIsolatePlatformData* ForIsolate(v8::Isolate* isolate); + std::shared_ptr<PerIsolatePlatformData> ForIsolate(v8::Isolate* isolate); Mutex per_isolate_mutex_; - std::unordered_map<v8::Isolate*, PerIsolatePlatformData*> per_isolate_; - TaskQueue<v8::Task> background_tasks_; - std::vector<std::unique_ptr<uv_thread_t>> threads_; + std::unordered_map<v8::Isolate*, + std::shared_ptr<PerIsolatePlatformData>> per_isolate_; std::unique_ptr<v8::TracingController> tracing_controller_; + std::shared_ptr<BackgroundTaskRunner> background_task_runner_; }; } // namespace node |