Skip to content

Commit

Permalink
Break out platform delegate
Browse files Browse the repository at this point in the history
  • Loading branch information
laverdet committed Nov 6, 2019
1 parent ed2c3ca commit cfc2ca9
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 18 deletions.
12 changes: 12 additions & 0 deletions src/node.h
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,15 @@ 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;
private:
friend class NodePlatform;
virtual class PerIsolatePlatformData* NodePerIsolate() { return nullptr; }
};

class NODE_EXTERN MultiIsolatePlatform : public v8::Platform {
public:
~MultiIsolatePlatform() override = default;
Expand All @@ -273,6 +282,9 @@ 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;
virtual void RegisterIsolate(
v8::Isolate* isolate,
std::shared_ptr<IsolatePlatformDelegate> delegate);

// This function may only be called once per `Isolate`, and discard any
// pending delayed tasks scheduled for that isolate.
Expand Down
57 changes: 41 additions & 16 deletions src/node_platform.cc
Original file line number Diff line number Diff line change
Expand Up @@ -221,6 +221,12 @@ int WorkerThreadsTaskRunner::NumberOfWorkerThreads() const {
return threads_.size();
}

void MultiIsolatePlatform::RegisterIsolate(
v8::Isolate* isolate,
std::shared_ptr<IsolatePlatformDelegate> delegate) {
UNREACHABLE();
}

PerIsolatePlatformData::PerIsolatePlatformData(
Isolate* isolate, uv_loop_t* loop)
: loop_(loop) {
Expand All @@ -230,6 +236,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();
Expand Down Expand Up @@ -267,7 +278,7 @@ void PerIsolatePlatformData::PostNonNestableDelayedTask(
}

PerIsolatePlatformData::~PerIsolatePlatformData() {
Shutdown();
CHECK(!flush_tasks_);
}

void PerIsolatePlatformData::AddShutdownCallback(void (*callback)(void*),
Expand Down Expand Up @@ -324,31 +335,38 @@ NodePlatform::NodePlatform(int thread_pool_size,
}

void NodePlatform::RegisterIsolate(Isolate* isolate, uv_loop_t* loop) {
RegisterIsolate(
isolate, std::make_shared<PerIsolatePlatformData>(isolate, loop));
}

void NodePlatform::RegisterIsolate(
Isolate* isolate,
std::shared_ptr<IsolatePlatformDelegate> delegate) {
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 insertion = per_isolate_.emplace(isolate, std::move(delegate));
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());
PerIsolatePlatformData* node_data = existing_it->second->NodePerIsolate();
if (node_data) {
node_data->Shutdown();
}
per_isolate_.erase(existing_it);
}

void NodePlatform::AddIsolateFinishedCallback(Isolate* isolate,
void (*cb)(void*), void* data) {
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);
it->second->NodePerIsolate()->AddShutdownCallback(cb, data);
}

void NodePlatform::Shutdown() {
Expand Down Expand Up @@ -394,7 +412,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.
Expand Down Expand Up @@ -452,23 +470,30 @@ void NodePlatform::CallDelayedOnWorkerThread(std::unique_ptr<Task> task,
}


std::shared_ptr<PerIsolatePlatformData>
std::shared_ptr<IsolatePlatformDelegate>
NodePlatform::ForIsolate(Isolate* isolate) {
Mutex::ScopedLock lock(per_isolate_mutex_);
std::shared_ptr<PerIsolatePlatformData> data = per_isolate_[isolate];
std::shared_ptr<IsolatePlatformDelegate> data = per_isolate_[isolate];
CHECK(data);
return data;
}

std::shared_ptr<PerIsolatePlatformData>
NodePlatform::ForNodeIsolate(Isolate* isolate) {
std::shared_ptr<IsolatePlatformDelegate> data = ForIsolate(isolate);
CHECK(data->NodePerIsolate());
return std::static_pointer_cast<PerIsolatePlatformData>(std::move(data));
}

bool NodePlatform::FlushForegroundTasks(Isolate* isolate) {
return ForIsolate(isolate)->FlushForegroundTasksInternal();
return ForNodeIsolate(isolate)->FlushForegroundTasksInternal();
}

bool NodePlatform::IdleTasksEnabled(Isolate* isolate) { return false; }

std::shared_ptr<v8::TaskRunner>
NodePlatform::GetForegroundTaskRunner(Isolate* isolate) {
return ForIsolate(isolate);
return ForIsolate(isolate)->GetForegroundTaskRunner();
}

double NodePlatform::MonotonicallyIncreasingTime() {
Expand Down
12 changes: 10 additions & 2 deletions src/node_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,20 @@ 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,
double delay_in_seconds) override;
bool IdleTasksEnabled() override { return false; }
PerIsolatePlatformData* NodePerIsolate() final { return this; }

// Non-nestable tasks are treated like regular tasks.
bool NonNestableTasksEnabled() const override { return true; }
Expand Down Expand Up @@ -162,6 +165,10 @@ 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,
std::shared_ptr<IsolatePlatformDelegate> delegate) override;

void UnregisterIsolate(v8::Isolate* isolate) override;
void AddIsolateFinishedCallback(v8::Isolate* isolate,
void (*callback)(void*), void* data) override;
Expand All @@ -170,11 +177,12 @@ class NodePlatform : public MultiIsolatePlatform {
v8::Isolate* isolate) override;

private:
std::shared_ptr<PerIsolatePlatformData> ForIsolate(v8::Isolate* isolate);
std::shared_ptr<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_;
std::shared_ptr<IsolatePlatformDelegate>> per_isolate_;

node::tracing::TracingController* tracing_controller_;
std::shared_ptr<WorkerThreadsTaskRunner> worker_thread_task_runner_;
Expand Down

0 comments on commit cfc2ca9

Please sign in to comment.