mirror of https://github.com/nodejs/node.git
src: make implementing CancelPendingDelayedTasks for platform optional
Fold `CancelPendingDelayedTasks()` into `UnregisterIsolate()` and make implementing it optional. It makes sense for these two operations to happen at the same time, so it is sufficient to provide a single operation instead of two separate ones. PR-URL: https://github.com/nodejs/node/pull/30034 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Shelley Vohr <codebytere@gmail.com>pull/30069/head
parent
45efe67a84
commit
2dc70657a3
|
@ -260,7 +260,11 @@ class NODE_EXTERN MultiIsolatePlatform : public v8::Platform {
|
||||||
// flushing.
|
// flushing.
|
||||||
virtual bool FlushForegroundTasks(v8::Isolate* isolate) = 0;
|
virtual bool FlushForegroundTasks(v8::Isolate* isolate) = 0;
|
||||||
virtual void DrainTasks(v8::Isolate* isolate) = 0;
|
virtual void DrainTasks(v8::Isolate* isolate) = 0;
|
||||||
virtual void CancelPendingDelayedTasks(v8::Isolate* isolate) = 0;
|
|
||||||
|
// TODO(addaleax): Remove this, it is unnecessary.
|
||||||
|
// This would currently be called before `UnregisterIsolate()` but will be
|
||||||
|
// folded into it in the future.
|
||||||
|
virtual void CancelPendingDelayedTasks(v8::Isolate* isolate);
|
||||||
|
|
||||||
// This needs to be called between the calls to `Isolate::Allocate()` and
|
// This needs to be called between the calls to `Isolate::Allocate()` and
|
||||||
// `Isolate::Initialize()`, so that initialization can already start
|
// `Isolate::Initialize()`, so that initialization can already start
|
||||||
|
@ -270,7 +274,8 @@ class NODE_EXTERN MultiIsolatePlatform : public v8::Platform {
|
||||||
virtual void RegisterIsolate(v8::Isolate* isolate,
|
virtual void RegisterIsolate(v8::Isolate* isolate,
|
||||||
struct uv_loop_s* loop) = 0;
|
struct uv_loop_s* loop) = 0;
|
||||||
// This needs to be called right before calling `Isolate::Dispose()`.
|
// This needs to be called right before calling `Isolate::Dispose()`.
|
||||||
// This function may only be called once per `Isolate`.
|
// This function may only be called once per `Isolate`, and discard any
|
||||||
|
// pending delayed tasks scheduled for that isolate.
|
||||||
virtual void UnregisterIsolate(v8::Isolate* isolate) = 0;
|
virtual void UnregisterIsolate(v8::Isolate* isolate) = 0;
|
||||||
// The platform should call the passed function once all state associated
|
// The platform should call the passed function once all state associated
|
||||||
// with the given isolate has been cleaned up. This can, but does not have to,
|
// with the given isolate has been cleaned up. This can, but does not have to,
|
||||||
|
|
|
@ -155,7 +155,6 @@ int NodeMainInstance::Run() {
|
||||||
RunAtExit(env.get());
|
RunAtExit(env.get());
|
||||||
|
|
||||||
per_process::v8_platform.DrainVMTasks(isolate_);
|
per_process::v8_platform.DrainVMTasks(isolate_);
|
||||||
per_process::v8_platform.CancelVMTasks(isolate_);
|
|
||||||
|
|
||||||
#if defined(LEAK_SANITIZER)
|
#if defined(LEAK_SANITIZER)
|
||||||
__lsan_do_leak_check();
|
__lsan_do_leak_check();
|
||||||
|
|
|
@ -285,22 +285,33 @@ void PerIsolatePlatformData::Shutdown() {
|
||||||
// effectively deleting the tasks instead of running them.
|
// effectively deleting the tasks instead of running them.
|
||||||
foreground_delayed_tasks_.PopAll();
|
foreground_delayed_tasks_.PopAll();
|
||||||
foreground_tasks_.PopAll();
|
foreground_tasks_.PopAll();
|
||||||
|
scheduled_delayed_tasks_.clear();
|
||||||
|
|
||||||
CancelPendingDelayedTasks();
|
// Both destroying the scheduled_delayed_tasks_ lists and closing
|
||||||
|
// flush_tasks_ handle add tasks to the event loop. We keep a count of all
|
||||||
ShutdownCbList* copy = new ShutdownCbList(std::move(shutdown_callbacks_));
|
// non-closed handles, and when that reaches zero, we inform any shutdown
|
||||||
flush_tasks_->data = copy;
|
// callbacks that the platform is done as far as this Isolate is concerned.
|
||||||
|
self_reference_ = shared_from_this();
|
||||||
uv_close(reinterpret_cast<uv_handle_t*>(flush_tasks_),
|
uv_close(reinterpret_cast<uv_handle_t*>(flush_tasks_),
|
||||||
[](uv_handle_t* handle) {
|
[](uv_handle_t* handle) {
|
||||||
std::unique_ptr<ShutdownCbList> callbacks(
|
std::unique_ptr<uv_async_t> flush_tasks {
|
||||||
static_cast<ShutdownCbList*>(handle->data));
|
reinterpret_cast<uv_async_t*>(handle) };
|
||||||
for (const auto& callback : *callbacks)
|
PerIsolatePlatformData* platform_data =
|
||||||
callback.cb(callback.data);
|
static_cast<PerIsolatePlatformData*>(flush_tasks->data);
|
||||||
delete reinterpret_cast<uv_async_t*>(handle);
|
platform_data->DecreaseHandleCount();
|
||||||
|
platform_data->self_reference_.reset();
|
||||||
});
|
});
|
||||||
flush_tasks_ = nullptr;
|
flush_tasks_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void PerIsolatePlatformData::DecreaseHandleCount() {
|
||||||
|
CHECK_GE(uv_handle_count_, 1);
|
||||||
|
if (--uv_handle_count_ == 0) {
|
||||||
|
for (const auto& callback : shutdown_callbacks_)
|
||||||
|
callback.cb(callback.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NodePlatform::NodePlatform(int thread_pool_size,
|
NodePlatform::NodePlatform(int thread_pool_size,
|
||||||
TracingController* tracing_controller) {
|
TracingController* tracing_controller) {
|
||||||
if (tracing_controller) {
|
if (tracing_controller) {
|
||||||
|
@ -382,10 +393,6 @@ void PerIsolatePlatformData::RunForegroundTask(uv_timer_t* handle) {
|
||||||
delayed->platform_data->DeleteFromScheduledTasks(delayed);
|
delayed->platform_data->DeleteFromScheduledTasks(delayed);
|
||||||
}
|
}
|
||||||
|
|
||||||
void PerIsolatePlatformData::CancelPendingDelayedTasks() {
|
|
||||||
scheduled_delayed_tasks_.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
void NodePlatform::DrainTasks(Isolate* isolate) {
|
void NodePlatform::DrainTasks(Isolate* isolate) {
|
||||||
std::shared_ptr<PerIsolatePlatformData> per_isolate = ForIsolate(isolate);
|
std::shared_ptr<PerIsolatePlatformData> per_isolate = ForIsolate(isolate);
|
||||||
|
|
||||||
|
@ -409,12 +416,15 @@ bool PerIsolatePlatformData::FlushForegroundTasksInternal() {
|
||||||
// the delay is non-zero. This should not be a problem in practice.
|
// the delay is non-zero. This should not be a problem in practice.
|
||||||
uv_timer_start(&delayed->timer, RunForegroundTask, delay_millis, 0);
|
uv_timer_start(&delayed->timer, RunForegroundTask, delay_millis, 0);
|
||||||
uv_unref(reinterpret_cast<uv_handle_t*>(&delayed->timer));
|
uv_unref(reinterpret_cast<uv_handle_t*>(&delayed->timer));
|
||||||
|
uv_handle_count_++;
|
||||||
|
|
||||||
scheduled_delayed_tasks_.emplace_back(delayed.release(),
|
scheduled_delayed_tasks_.emplace_back(delayed.release(),
|
||||||
[](DelayedTask* delayed) {
|
[](DelayedTask* delayed) {
|
||||||
uv_close(reinterpret_cast<uv_handle_t*>(&delayed->timer),
|
uv_close(reinterpret_cast<uv_handle_t*>(&delayed->timer),
|
||||||
[](uv_handle_t* handle) {
|
[](uv_handle_t* handle) {
|
||||||
delete static_cast<DelayedTask*>(handle->data);
|
std::unique_ptr<DelayedTask> task {
|
||||||
|
static_cast<DelayedTask*>(handle->data) };
|
||||||
|
task->platform_data->DecreaseHandleCount();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -454,10 +464,6 @@ bool NodePlatform::FlushForegroundTasks(Isolate* isolate) {
|
||||||
return ForIsolate(isolate)->FlushForegroundTasksInternal();
|
return ForIsolate(isolate)->FlushForegroundTasksInternal();
|
||||||
}
|
}
|
||||||
|
|
||||||
void NodePlatform::CancelPendingDelayedTasks(Isolate* isolate) {
|
|
||||||
ForIsolate(isolate)->CancelPendingDelayedTasks();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool NodePlatform::IdleTasksEnabled(Isolate* isolate) { return false; }
|
bool NodePlatform::IdleTasksEnabled(Isolate* isolate) { return false; }
|
||||||
|
|
||||||
std::shared_ptr<v8::TaskRunner>
|
std::shared_ptr<v8::TaskRunner>
|
||||||
|
@ -548,4 +554,6 @@ std::queue<std::unique_ptr<T>> TaskQueue<T>::PopAll() {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MultiIsolatePlatform::CancelPendingDelayedTasks(Isolate* isolate) {}
|
||||||
|
|
||||||
} // namespace node
|
} // namespace node
|
||||||
|
|
|
@ -78,12 +78,12 @@ class PerIsolatePlatformData :
|
||||||
// posted during flushing of the queue are postponed until the next
|
// posted during flushing of the queue are postponed until the next
|
||||||
// flushing.
|
// flushing.
|
||||||
bool FlushForegroundTasksInternal();
|
bool FlushForegroundTasksInternal();
|
||||||
void CancelPendingDelayedTasks();
|
|
||||||
|
|
||||||
const uv_loop_t* event_loop() const { return loop_; }
|
const uv_loop_t* event_loop() const { return loop_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void DeleteFromScheduledTasks(DelayedTask* task);
|
void DeleteFromScheduledTasks(DelayedTask* task);
|
||||||
|
void DecreaseHandleCount();
|
||||||
|
|
||||||
static void FlushTasks(uv_async_t* handle);
|
static void FlushTasks(uv_async_t* handle);
|
||||||
static void RunForegroundTask(std::unique_ptr<v8::Task> task);
|
static void RunForegroundTask(std::unique_ptr<v8::Task> task);
|
||||||
|
@ -95,6 +95,9 @@ class PerIsolatePlatformData :
|
||||||
};
|
};
|
||||||
typedef std::vector<ShutdownCallback> ShutdownCbList;
|
typedef std::vector<ShutdownCallback> ShutdownCbList;
|
||||||
ShutdownCbList shutdown_callbacks_;
|
ShutdownCbList shutdown_callbacks_;
|
||||||
|
// shared_ptr to self to keep this object alive during shutdown.
|
||||||
|
std::shared_ptr<PerIsolatePlatformData> self_reference_;
|
||||||
|
uint32_t uv_handle_count_ = 1; // 1 = flush_tasks_
|
||||||
|
|
||||||
uv_loop_t* const loop_;
|
uv_loop_t* const loop_;
|
||||||
uv_async_t* flush_tasks_ = nullptr;
|
uv_async_t* flush_tasks_ = nullptr;
|
||||||
|
@ -102,7 +105,7 @@ class PerIsolatePlatformData :
|
||||||
TaskQueue<DelayedTask> foreground_delayed_tasks_;
|
TaskQueue<DelayedTask> foreground_delayed_tasks_;
|
||||||
|
|
||||||
// Use a custom deleter because libuv needs to close the handle first.
|
// Use a custom deleter because libuv needs to close the handle first.
|
||||||
typedef std::unique_ptr<DelayedTask, std::function<void(DelayedTask*)>>
|
typedef std::unique_ptr<DelayedTask, void(*)(DelayedTask*)>
|
||||||
DelayedTaskPointer;
|
DelayedTaskPointer;
|
||||||
std::vector<DelayedTaskPointer> scheduled_delayed_tasks_;
|
std::vector<DelayedTaskPointer> scheduled_delayed_tasks_;
|
||||||
};
|
};
|
||||||
|
@ -137,7 +140,6 @@ class NodePlatform : public MultiIsolatePlatform {
|
||||||
~NodePlatform() override = default;
|
~NodePlatform() override = default;
|
||||||
|
|
||||||
void DrainTasks(v8::Isolate* isolate) override;
|
void DrainTasks(v8::Isolate* isolate) override;
|
||||||
void CancelPendingDelayedTasks(v8::Isolate* isolate) override;
|
|
||||||
void Shutdown();
|
void Shutdown();
|
||||||
|
|
||||||
// v8::Platform implementation.
|
// v8::Platform implementation.
|
||||||
|
|
|
@ -113,10 +113,6 @@ struct V8Platform {
|
||||||
platform_->DrainTasks(isolate);
|
platform_->DrainTasks(isolate);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void CancelVMTasks(v8::Isolate* isolate) {
|
|
||||||
platform_->CancelPendingDelayedTasks(isolate);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void StartTracingAgent() {
|
inline void StartTracingAgent() {
|
||||||
// Attach a new NodeTraceWriter only if this function hasn't been called
|
// Attach a new NodeTraceWriter only if this function hasn't been called
|
||||||
// before.
|
// before.
|
||||||
|
@ -150,7 +146,6 @@ struct V8Platform {
|
||||||
inline void Initialize(int thread_pool_size) {}
|
inline void Initialize(int thread_pool_size) {}
|
||||||
inline void Dispose() {}
|
inline void Dispose() {}
|
||||||
inline void DrainVMTasks(v8::Isolate* isolate) {}
|
inline void DrainVMTasks(v8::Isolate* isolate) {}
|
||||||
inline void CancelVMTasks(v8::Isolate* isolate) {}
|
|
||||||
inline void StartTracingAgent() {
|
inline void StartTracingAgent() {
|
||||||
if (!per_process::cli_options->trace_event_categories.empty()) {
|
if (!per_process::cli_options->trace_event_categories.empty()) {
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
|
|
|
@ -148,8 +148,6 @@ class WorkerThreadData {
|
||||||
w_->isolate_ = nullptr;
|
w_->isolate_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
w_->platform_->CancelPendingDelayedTasks(isolate);
|
|
||||||
|
|
||||||
bool platform_finished = false;
|
bool platform_finished = false;
|
||||||
|
|
||||||
isolate_data_.reset();
|
isolate_data_.reset();
|
||||||
|
|
Loading…
Reference in New Issue