Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

src: use unique_ptr in platform implementation #16970

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
68 changes: 34 additions & 34 deletions src/node_platform.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@ using v8::TracingController;

static void BackgroundRunner(void* data) {
TaskQueue<Task>* background_tasks = static_cast<TaskQueue<Task>*>(data);
while (Task* task = background_tasks->BlockingPop()) {
while (std::unique_ptr<Task> task = background_tasks->BlockingPop()) {
task->Run();
delete task;
background_tasks->NotifyOfCompletion();
}
}
Expand All @@ -39,18 +38,19 @@ void PerIsolatePlatformData::FlushTasks(uv_async_t* handle) {
platform_data->FlushForegroundTasksInternal();
}

void PerIsolatePlatformData::CallOnForegroundThread(Task* task) {
foreground_tasks_.Push(task);
void PerIsolatePlatformData::CallOnForegroundThread(
std::unique_ptr<Task> task) {
foreground_tasks_.Push(std::move(task));
uv_async_send(flush_tasks_);
}

void PerIsolatePlatformData::CallDelayedOnForegroundThread(
Task* task, double delay_in_seconds) {
auto delayed = new DelayedTask();
delayed->task = task;
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->timeout = delay_in_seconds;
foreground_delayed_tasks_.Push(delayed);
foreground_delayed_tasks_.Push(std::move(delayed));
uv_async_send(flush_tasks_);
}

Expand Down Expand Up @@ -125,14 +125,13 @@ size_t NodePlatform::NumberOfAvailableBackgroundThreads() {
return threads_.size();
}

void PerIsolatePlatformData::RunForegroundTask(Task* task) {
void PerIsolatePlatformData::RunForegroundTask(std::unique_ptr<Task> task) {
Isolate* isolate = Isolate::GetCurrent();
HandleScope scope(isolate);
Environment* env = Environment::GetCurrent(isolate);
InternalCallbackScope cb_scope(env, Local<Object>(), { 0, 0 },
InternalCallbackScope::kAllowEmptyResource);
task->Run();
delete task;
}

void PerIsolatePlatformData::RunForegroundTask(uv_timer_t* handle) {
Expand All @@ -141,7 +140,7 @@ void PerIsolatePlatformData::RunForegroundTask(uv_timer_t* handle) {
auto it = std::find(tasklist.begin(), tasklist.end(), delayed);
CHECK_NE(it, tasklist.end());
tasklist.erase(it);
RunForegroundTask(delayed->task);
RunForegroundTask(std::move(delayed->task));
uv_close(reinterpret_cast<uv_handle_t*>(&delayed->timer),
[](uv_handle_t* handle) {
delete static_cast<DelayedTask*>(handle->data);
Expand All @@ -162,39 +161,40 @@ void NodePlatform::DrainBackgroundTasks(Isolate* isolate) {
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.
// 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();
} while (per_isolate->FlushForegroundTasksInternal());
}

bool PerIsolatePlatformData::FlushForegroundTasksInternal() {
bool did_work = false;

while (auto delayed = foreground_delayed_tasks_.Pop()) {
while (std::unique_ptr<DelayedTask> delayed =
foreground_delayed_tasks_.Pop()) {
did_work = true;
uint64_t delay_millis =
static_cast<uint64_t>(delayed->timeout + 0.5) * 1000;
delayed->timer.data = static_cast<void*>(delayed);
delayed->timer.data = static_cast<void*>(delayed.get());
uv_timer_init(loop_, &delayed->timer);
// Timers may not guarantee queue ordering of events with the same delay if
// the delay is non-zero. This should not be a problem in practice.
uv_timer_start(&delayed->timer, RunForegroundTask, delay_millis, 0);
uv_unref(reinterpret_cast<uv_handle_t*>(&delayed->timer));
scheduled_delayed_tasks_.push_back(delayed);
scheduled_delayed_tasks_.push_back(delayed.release());
}
while (Task* task = foreground_tasks_.Pop()) {
while (std::unique_ptr<Task> task = foreground_tasks_.Pop()) {
did_work = true;
RunForegroundTask(task);
RunForegroundTask(std::move(task));
}
return did_work;
}

void NodePlatform::CallOnBackgroundThread(Task* task,
ExpectedRuntime expected_runtime) {
background_tasks_.Push(task);
background_tasks_.Push(std::unique_ptr<Task>(task));
}

PerIsolatePlatformData* NodePlatform::ForIsolate(Isolate* isolate) {
Expand All @@ -205,14 +205,14 @@ PerIsolatePlatformData* NodePlatform::ForIsolate(Isolate* isolate) {
}

void NodePlatform::CallOnForegroundThread(Isolate* isolate, Task* task) {
ForIsolate(isolate)->CallOnForegroundThread(task);
ForIsolate(isolate)->CallOnForegroundThread(std::unique_ptr<Task>(task));
}

void NodePlatform::CallDelayedOnForegroundThread(Isolate* isolate,
Task* task,
double delay_in_seconds) {
ForIsolate(isolate)->CallDelayedOnForegroundThread(task,
delay_in_seconds);
ForIsolate(isolate)->CallDelayedOnForegroundThread(
std::unique_ptr<Task>(task), delay_in_seconds);
}

void NodePlatform::FlushForegroundTasks(v8::Isolate* isolate) {
Expand Down Expand Up @@ -240,34 +240,34 @@ TaskQueue<T>::TaskQueue()
outstanding_tasks_(0), stopped_(false), task_queue_() { }

template <class T>
void TaskQueue<T>::Push(T* task) {
void TaskQueue<T>::Push(std::unique_ptr<T> task) {
Mutex::ScopedLock scoped_lock(lock_);
outstanding_tasks_++;
task_queue_.push(task);
task_queue_.push(std::move(task));
tasks_available_.Signal(scoped_lock);
}

template <class T>
T* TaskQueue<T>::Pop() {
std::unique_ptr<T> TaskQueue<T>::Pop() {
Mutex::ScopedLock scoped_lock(lock_);
T* result = nullptr;
if (!task_queue_.empty()) {
result = task_queue_.front();
task_queue_.pop();
if (task_queue_.empty()) {
return std::unique_ptr<T>(nullptr);
}
std::unique_ptr<T> result = std::move(task_queue_.front());
task_queue_.pop();
return result;
}

template <class T>
T* TaskQueue<T>::BlockingPop() {
std::unique_ptr<T> TaskQueue<T>::BlockingPop() {
Mutex::ScopedLock scoped_lock(lock_);
while (task_queue_.empty() && !stopped_) {
tasks_available_.Wait(scoped_lock);
}
if (stopped_) {
return nullptr;
return std::unique_ptr<T>(nullptr);
}
T* result = task_queue_.front();
std::unique_ptr<T> result = std::move(task_queue_.front());
task_queue_.pop();
return result;
}
Expand Down
17 changes: 9 additions & 8 deletions src/node_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ class TaskQueue {
TaskQueue();
~TaskQueue() {}

void Push(T* task);
T* Pop();
T* BlockingPop();
void Push(std::unique_ptr<T> task);
std::unique_ptr<T> Pop();
std::unique_ptr<T> BlockingPop();
void NotifyOfCompletion();
void BlockingDrain();
void Stop();
Expand All @@ -35,11 +35,11 @@ class TaskQueue {
ConditionVariable tasks_drained_;
int outstanding_tasks_;
bool stopped_;
std::queue<T*> task_queue_;
std::queue<std::unique_ptr<T>> task_queue_;
};

struct DelayedTask {
v8::Task* task;
std::unique_ptr<v8::Task> task;
uv_timer_t timer;
double timeout;
PerIsolatePlatformData* platform_data;
Expand All @@ -50,8 +50,9 @@ class PerIsolatePlatformData {
PerIsolatePlatformData(v8::Isolate* isolate, uv_loop_t* loop);
~PerIsolatePlatformData();

void CallOnForegroundThread(v8::Task* task);
void CallDelayedOnForegroundThread(v8::Task* task, double delay_in_seconds);
void CallOnForegroundThread(std::unique_ptr<v8::Task> task);
void CallDelayedOnForegroundThread(std::unique_ptr<v8::Task> task,
double delay_in_seconds);

void Shutdown();

Expand All @@ -64,7 +65,7 @@ class PerIsolatePlatformData {

private:
static void FlushTasks(uv_async_t* handle);
static void RunForegroundTask(v8::Task* task);
static void RunForegroundTask(std::unique_ptr<v8::Task> task);
static void RunForegroundTask(uv_timer_t* timer);

int ref_count_ = 1;
Expand Down