@@ -157,16 +157,9 @@ class WorkerThreadsTaskRunner::DelayedTaskScheduler { |
157 | 157 | DelayedTaskScheduler* scheduler = |
158 | 158 | ContainerOf(&DelayedTaskScheduler::loop_, flush_tasks->loop); |
159 | 159 |
|
160 | | - auto tasks_to_run = scheduler->tasks_.Lock().PopAll(); |
161 | | - while (!tasks_to_run.empty()) { |
162 | | - // We have to use const_cast because std::priority_queue::top() does not |
163 | | - // return a movable item. |
164 | | - std::unique_ptr<Task> task = |
165 | | - std::move(const_cast<std::unique_ptr<Task>&>(tasks_to_run.top())); |
166 | | - tasks_to_run.pop(); |
167 | | - // This runs either the ScheduleTasks that scheduels the timers to |
168 | | - // pop the tasks back into the worker task runner queue, or the |
169 | | - // or the StopTasks to stop the timers and drop all the pending tasks. |
| 160 | + // ScheduleTasks (start a timer that pops the task into the worker queue) |
| 161 | + // in posting order, then, once Stop() was called, the StopTask. |
| 162 | + for (std::unique_ptr<Task>& task : scheduler->tasks_.Lock().PopAll()) { |
170 | 163 | task->Run(); |
171 | 164 | } |
172 | 165 | } |
@@ -611,15 +604,8 @@ void NodePlatform::DrainTasks(Isolate* isolate) { |
611 | 604 | bool PerIsolatePlatformData::FlushForegroundTasksInternal() { |
612 | 605 | bool did_work = false; |
613 | 606 |
|
614 | | - auto delayed_tasks_to_schedule = foreground_delayed_tasks_.Lock().PopAll(); |
615 | | - while (!delayed_tasks_to_schedule.empty()) { |
616 | | - // We have to use const_cast because std::priority_queue::top() does not |
617 | | - // return a movable item. |
618 | | - std::unique_ptr<DelayedTask> delayed = |
619 | | - std::move(const_cast<std::unique_ptr<DelayedTask>&>( |
620 | | - delayed_tasks_to_schedule.top())); |
621 | | - delayed_tasks_to_schedule.pop(); |
622 | | - |
| 607 | + for (std::unique_ptr<DelayedTask>& delayed : |
| 608 | + foreground_delayed_tasks_.Lock().PopAll()) { |
623 | 609 | did_work = true; |
624 | 610 | uint64_t delay_millis = llround(delayed->timeout * 1000); |
625 | 611 |
|
@@ -642,18 +628,8 @@ bool PerIsolatePlatformData::FlushForegroundTasksInternal() { |
642 | 628 | }); |
643 | 629 | } |
644 | 630 |
|
645 | | - TaskQueue<TaskQueueEntry>::PriorityQueue tasks; |
646 | | - { |
647 | | - auto locked = foreground_tasks_.Lock(); |
648 | | - tasks = locked.PopAll(); |
649 | | - } |
650 | | - |
651 | | - while (!tasks.empty()) { |
652 | | - // We have to use const_cast because std::priority_queue::top() does not |
653 | | - // return a movable item. |
654 | | - std::unique_ptr<TaskQueueEntry> entry = |
655 | | - std::move(const_cast<std::unique_ptr<TaskQueueEntry>&>(tasks.top())); |
656 | | - tasks.pop(); |
| 631 | + for (std::unique_ptr<TaskQueueEntry>& entry : |
| 632 | + foreground_tasks_.Lock().PopAll()) { |
657 | 633 | did_work = true; |
658 | 634 | RunForegroundTask(std::move(entry->task)); |
659 | 635 | } |
@@ -788,12 +764,21 @@ template <class T> |
788 | 764 | TaskQueue<T>::Locked::Locked(TaskQueue* queue) |
789 | 765 | : queue_(queue), lock_(queue->lock_) {} |
790 | 766 |
|
| 767 | +template <class T> |
| 768 | +std::unique_ptr<T> TaskQueue<T>::PopTask() { |
| 769 | + // std::priority_queue::top() only hands out a const reference. |
| 770 | + Item& top = const_cast<Item&>(task_queue_.top()); |
| 771 | + std::unique_ptr<T> task = std::move(top.task); |
| 772 | + task_queue_.pop(); |
| 773 | + return task; |
| 774 | +} |
| 775 | + |
791 | 776 | template <class T> |
792 | 777 | void TaskQueue<T>::Locked::Push(std::unique_ptr<T> task, bool outstanding) { |
793 | 778 | if (outstanding) { |
794 | 779 | queue_->outstanding_tasks_++; |
795 | 780 | } |
796 | | - queue_->task_queue_.push(std::move(task)); |
| 781 | + queue_->task_queue_.push({std::move(task), queue_->next_sequence_++}); |
797 | 782 | queue_->tasks_available_.Signal(lock_); |
798 | 783 | } |
799 | 784 |
|
@@ -802,10 +787,7 @@ std::unique_ptr<T> TaskQueue<T>::Locked::Pop() { |
802 | 787 | if (queue_->task_queue_.empty()) { |
803 | 788 | return std::unique_ptr<T>(nullptr); |
804 | 789 | } |
805 | | - std::unique_ptr<T> result = std::move( |
806 | | - std::move(const_cast<std::unique_ptr<T>&>(queue_->task_queue_.top()))); |
807 | | - queue_->task_queue_.pop(); |
808 | | - return result; |
| 790 | + return queue_->PopTask(); |
809 | 791 | } |
810 | 792 |
|
811 | 793 | template <class T> |
@@ -816,10 +798,7 @@ std::unique_ptr<T> TaskQueue<T>::Locked::BlockingPop() { |
816 | 798 | if (queue_->stopped_) { |
817 | 799 | return std::unique_ptr<T>(nullptr); |
818 | 800 | } |
819 | | - std::unique_ptr<T> result = std::move( |
820 | | - std::move(const_cast<std::unique_ptr<T>&>(queue_->task_queue_.top()))); |
821 | | - queue_->task_queue_.pop(); |
822 | | - return result; |
| 801 | + return queue_->PopTask(); |
823 | 802 | } |
824 | 803 |
|
825 | 804 | template <class T> |
@@ -843,12 +822,19 @@ void TaskQueue<T>::Locked::Stop() { |
843 | 822 | } |
844 | 823 |
|
845 | 824 | template <class T> |
846 | | -TaskQueue<T>::PriorityQueue TaskQueue<T>::Locked::PopAll() { |
847 | | - TaskQueue<T>::PriorityQueue result; |
848 | | - result.swap(queue_->task_queue_); |
| 825 | +std::vector<std::unique_ptr<T>> TaskQueue<T>::Locked::PopAll() { |
| 826 | + std::vector<std::unique_ptr<T>> result; |
| 827 | + result.reserve(queue_->task_queue_.size()); |
| 828 | + while (!queue_->task_queue_.empty()) { |
| 829 | + result.push_back(queue_->PopTask()); |
| 830 | + } |
849 | 831 | return result; |
850 | 832 | } |
851 | 833 |
|
| 834 | +template class TaskQueue<Task>; |
| 835 | +template class TaskQueue<TaskQueueEntry>; |
| 836 | +template class TaskQueue<DelayedTask>; |
| 837 | + |
852 | 838 | void MultiIsolatePlatform::DisposeIsolate(Isolate* isolate) { |
853 | 839 | // The order of these calls is important. When the Isolate is disposed, |
854 | 840 | // it may still post tasks to the platform, so it must still be registered |
|