diff options
author | Marcel Laverdet <marcel@laverdet.com> | 2019-11-12 14:26:08 -0800 |
---|---|---|
committer | Anna Henningsen <anna@addaleax.net> | 2019-11-20 19:02:55 +0100 |
commit | c712fb7cd6222018cf615fd0071998bde6f16da9 (patch) | |
tree | 2f6713dc39dfea54e6fb6b1a56a82c9da64469a6 /src | |
parent | c63af4fea041673eb7c33f6df3c474d4537fe5eb (diff) | |
download | android-node-v8-c712fb7cd6222018cf615fd0071998bde6f16da9.tar.gz android-node-v8-c712fb7cd6222018cf615fd0071998bde6f16da9.tar.bz2 android-node-v8-c712fb7cd6222018cf615fd0071998bde6f16da9.zip |
src: add abstract `IsolatePlatformDelegate`
Adds a new abstract class for module authors and embedders to register
arbitrary isolates with `node::MultiIsolatePlatform`.
PR-URL: https://github.com/nodejs/node/pull/30324
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/node.h | 12 | ||||
-rw-r--r-- | src/node_platform.cc | 66 | ||||
-rw-r--r-- | src/node_platform.h | 13 |
3 files changed, 69 insertions, 22 deletions
diff --git a/src/node.h b/src/node.h index c80e626685..f3da457401 100644 --- a/src/node.h +++ b/src/node.h @@ -262,6 +262,12 @@ class NODE_EXTERN ArrayBufferAllocator : public v8::ArrayBuffer::Allocator { NODE_EXTERN ArrayBufferAllocator* CreateArrayBufferAllocator(); NODE_EXTERN void FreeArrayBufferAllocator(ArrayBufferAllocator* allocator); +class NODE_EXTERN IsolatePlatformDelegate { + public: + virtual std::shared_ptr<v8::TaskRunner> GetForegroundTaskRunner() = 0; + virtual bool IdleTasksEnabled() = 0; +}; + class NODE_EXTERN MultiIsolatePlatform : public v8::Platform { public: ~MultiIsolatePlatform() override = default; @@ -283,6 +289,12 @@ class NODE_EXTERN MultiIsolatePlatform : public v8::Platform { // This function may only be called once per `Isolate`. virtual void RegisterIsolate(v8::Isolate* isolate, struct uv_loop_s* loop) = 0; + // This method can be used when an application handles task scheduling on its + // own through `IsolatePlatformDelegate`. Upon registering an isolate with + // this overload any other method in this class with the exception of + // `UnregisterIsolate` *must not* be used on that isolate. + virtual void RegisterIsolate(v8::Isolate* isolate, + IsolatePlatformDelegate* delegate) = 0; // This function may only be called once per `Isolate`, and discard any // pending delayed tasks scheduled for that isolate. diff --git a/src/node_platform.cc b/src/node_platform.cc index 6e3b4abfee..383f67ce0f 100644 --- a/src/node_platform.cc +++ b/src/node_platform.cc @@ -230,6 +230,11 @@ PerIsolatePlatformData::PerIsolatePlatformData( uv_unref(reinterpret_cast<uv_handle_t*>(flush_tasks_)); } +std::shared_ptr<v8::TaskRunner> +PerIsolatePlatformData::GetForegroundTaskRunner() { + return shared_from_this(); +} + void PerIsolatePlatformData::FlushTasks(uv_async_t* handle) { auto platform_data = static_cast<PerIsolatePlatformData*>(handle->data); platform_data->FlushForegroundTasksInternal(); @@ -267,7 +272,7 @@ void PerIsolatePlatformData::PostNonNestableDelayedTask( } PerIsolatePlatformData::~PerIsolatePlatformData() { - Shutdown(); + CHECK(!flush_tasks_); } void PerIsolatePlatformData::AddShutdownCallback(void (*callback)(void*), @@ -325,18 +330,32 @@ NodePlatform::NodePlatform(int thread_pool_size, void NodePlatform::RegisterIsolate(Isolate* isolate, uv_loop_t* loop) { Mutex::ScopedLock lock(per_isolate_mutex_); - std::shared_ptr<PerIsolatePlatformData> existing = per_isolate_[isolate]; - CHECK(!existing); - per_isolate_[isolate] = - std::make_shared<PerIsolatePlatformData>(isolate, loop); + auto delegate = std::make_shared<PerIsolatePlatformData>(isolate, loop); + IsolatePlatformDelegate* ptr = delegate.get(); + auto insertion = per_isolate_.emplace( + isolate, + std::make_pair(ptr, std::move(delegate))); + CHECK(insertion.second); +} + +void NodePlatform::RegisterIsolate(Isolate* isolate, + IsolatePlatformDelegate* delegate) { + Mutex::ScopedLock lock(per_isolate_mutex_); + auto insertion = per_isolate_.emplace( + isolate, + std::make_pair(delegate, std::shared_ptr<PerIsolatePlatformData>{})); + CHECK(insertion.second); } void NodePlatform::UnregisterIsolate(Isolate* isolate) { Mutex::ScopedLock lock(per_isolate_mutex_); - std::shared_ptr<PerIsolatePlatformData> existing = per_isolate_[isolate]; - CHECK(existing); - existing->Shutdown(); - per_isolate_.erase(isolate); + auto existing_it = per_isolate_.find(isolate); + CHECK_NE(existing_it, per_isolate_.end()); + auto& existing = existing_it->second; + if (existing.second) { + existing.second->Shutdown(); + } + per_isolate_.erase(existing_it); } void NodePlatform::AddIsolateFinishedCallback(Isolate* isolate, @@ -344,11 +363,11 @@ void NodePlatform::AddIsolateFinishedCallback(Isolate* isolate, Mutex::ScopedLock lock(per_isolate_mutex_); auto it = per_isolate_.find(isolate); if (it == per_isolate_.end()) { - CHECK(it->second); cb(data); return; } - it->second->AddShutdownCallback(cb, data); + CHECK(it->second.second); + it->second.second->AddShutdownCallback(cb, data); } void NodePlatform::Shutdown() { @@ -394,7 +413,7 @@ void PerIsolatePlatformData::RunForegroundTask(uv_timer_t* handle) { } void NodePlatform::DrainTasks(Isolate* isolate) { - std::shared_ptr<PerIsolatePlatformData> per_isolate = ForIsolate(isolate); + std::shared_ptr<PerIsolatePlatformData> per_isolate = ForNodeIsolate(isolate); do { // Worker tasks aren't associated with an Isolate. @@ -452,23 +471,32 @@ void NodePlatform::CallDelayedOnWorkerThread(std::unique_ptr<Task> task, } +IsolatePlatformDelegate* NodePlatform::ForIsolate(Isolate* isolate) { + Mutex::ScopedLock lock(per_isolate_mutex_); + auto data = per_isolate_[isolate]; + CHECK_NOT_NULL(data.first); + return data.first; +} + std::shared_ptr<PerIsolatePlatformData> -NodePlatform::ForIsolate(Isolate* isolate) { +NodePlatform::ForNodeIsolate(Isolate* isolate) { Mutex::ScopedLock lock(per_isolate_mutex_); - std::shared_ptr<PerIsolatePlatformData> data = per_isolate_[isolate]; - CHECK(data); - return data; + auto data = per_isolate_[isolate]; + CHECK(data.second); + return data.second; } bool NodePlatform::FlushForegroundTasks(Isolate* isolate) { - return ForIsolate(isolate)->FlushForegroundTasksInternal(); + return ForNodeIsolate(isolate)->FlushForegroundTasksInternal(); } -bool NodePlatform::IdleTasksEnabled(Isolate* isolate) { return false; } +bool NodePlatform::IdleTasksEnabled(Isolate* isolate) { + return ForIsolate(isolate)->IdleTasksEnabled(); +} std::shared_ptr<v8::TaskRunner> NodePlatform::GetForegroundTaskRunner(Isolate* isolate) { - return ForIsolate(isolate); + return ForIsolate(isolate)->GetForegroundTaskRunner(); } double NodePlatform::MonotonicallyIncreasingTime() { diff --git a/src/node_platform.h b/src/node_platform.h index 24f7b337bb..e47d72b366 100644 --- a/src/node_platform.h +++ b/src/node_platform.h @@ -52,12 +52,14 @@ struct DelayedTask { // This acts as the foreground task runner for a given Isolate. class PerIsolatePlatformData : + public IsolatePlatformDelegate, public v8::TaskRunner, public std::enable_shared_from_this<PerIsolatePlatformData> { public: PerIsolatePlatformData(v8::Isolate* isolate, uv_loop_t* loop); ~PerIsolatePlatformData() override; + std::shared_ptr<v8::TaskRunner> GetForegroundTaskRunner() override; 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, @@ -162,6 +164,9 @@ class NodePlatform : public MultiIsolatePlatform { bool FlushForegroundTasks(v8::Isolate* isolate) override; void RegisterIsolate(v8::Isolate* isolate, uv_loop_t* loop) override; + void RegisterIsolate(v8::Isolate* isolate, + IsolatePlatformDelegate* delegate) override; + void UnregisterIsolate(v8::Isolate* isolate) override; void AddIsolateFinishedCallback(v8::Isolate* isolate, void (*callback)(void*), void* data) override; @@ -170,11 +175,13 @@ class NodePlatform : public MultiIsolatePlatform { v8::Isolate* isolate) override; private: - std::shared_ptr<PerIsolatePlatformData> ForIsolate(v8::Isolate* isolate); + IsolatePlatformDelegate* ForIsolate(v8::Isolate* isolate); + std::shared_ptr<PerIsolatePlatformData> ForNodeIsolate(v8::Isolate* isolate); Mutex per_isolate_mutex_; - std::unordered_map<v8::Isolate*, - std::shared_ptr<PerIsolatePlatformData>> per_isolate_; + using DelegatePair = std::pair< + IsolatePlatformDelegate*, std::shared_ptr<PerIsolatePlatformData>>; + std::unordered_map<v8::Isolate*, DelegatePair> per_isolate_; node::tracing::TracingController* tracing_controller_; std::shared_ptr<WorkerThreadsTaskRunner> worker_thread_task_runner_; |