@@ -18,7 +18,7 @@ using v8::TaskPriority;
18
18
namespace {
19
19
20
20
struct PlatformWorkerData {
21
- TaskQueue<Task >* task_queue;
21
+ TaskQueue<TaskQueueEntry >* task_queue;
22
22
Mutex* platform_workers_mutex;
23
23
ConditionVariable* platform_workers_ready;
24
24
int * pending_platform_workers;
@@ -53,7 +53,7 @@ static void PlatformWorkerThread(void* data) {
53
53
std::unique_ptr<PlatformWorkerData>
54
54
worker_data (static_cast <PlatformWorkerData*>(data));
55
55
56
- TaskQueue<Task >* pending_worker_tasks = worker_data->task_queue ;
56
+ TaskQueue<TaskQueueEntry >* pending_worker_tasks = worker_data->task_queue ;
57
57
TRACE_EVENT_METADATA1 (" __metadata" , " thread_name" , " name" ,
58
58
" PlatformWorkerThread" );
59
59
@@ -67,16 +67,17 @@ static void PlatformWorkerThread(void* data) {
67
67
bool debug_log_enabled =
68
68
worker_data->debug_log_level != PlatformDebugLogLevel::kNone ;
69
69
int id = worker_data->id ;
70
- while (std::unique_ptr<Task> task =
70
+ while (std::unique_ptr<TaskQueueEntry> entry =
71
71
pending_worker_tasks->Lock ().BlockingPop ()) {
72
72
if (debug_log_enabled) {
73
73
fprintf (stderr,
74
- " \n PlatformWorkerThread %d running task %p\n " ,
74
+ " \n PlatformWorkerThread %d running task %p %s \n " ,
75
75
id,
76
- task.get ());
76
+ entry->task .get (),
77
+ GetTaskPriorityName (entry->priority ));
77
78
fflush (stderr);
78
79
}
79
- task->Run ();
80
+ entry-> task ->Run ();
80
81
pending_worker_tasks->Lock ().NotifyOfCompletion ();
81
82
}
82
83
}
@@ -92,8 +93,8 @@ static int GetActualThreadPoolSize(int thread_pool_size) {
92
93
93
94
class WorkerThreadsTaskRunner ::DelayedTaskScheduler {
94
95
public:
95
- explicit DelayedTaskScheduler (TaskQueue<Task >* tasks)
96
- : pending_worker_tasks_(tasks) {}
96
+ explicit DelayedTaskScheduler (TaskQueue<TaskQueueEntry >* tasks)
97
+ : pending_worker_tasks_(tasks) {}
97
98
98
99
std::unique_ptr<uv_thread_t > Start () {
99
100
auto start_thread = [](void * data) {
@@ -107,16 +108,21 @@ class WorkerThreadsTaskRunner::DelayedTaskScheduler {
107
108
return t;
108
109
}
109
110
110
- void PostDelayedTask (std::unique_ptr<Task> task, double delay_in_seconds) {
111
+ void PostDelayedTask (v8::TaskPriority priority,
112
+ std::unique_ptr<Task> task,
113
+ double delay_in_seconds) {
111
114
auto locked = tasks_.Lock ();
112
115
116
+ auto entry = std::make_unique<TaskQueueEntry>(std::move (task), priority);
117
+ auto delayed = std::make_unique<ScheduleTask>(
118
+ this , std::move (entry), delay_in_seconds);
119
+
113
120
// The delayed task scheuler is on is own thread with its own loop that
114
121
// runs the timers for the scheduled tasks to pop the original task back
115
122
// into the the worker task queue. This first pushes the tasks that
116
123
// schedules the timers into the local task queue that will be flushed
117
124
// by the local event loop.
118
- locked.Push (std::make_unique<ScheduleTask>(
119
- this , std::move (task), delay_in_seconds));
125
+ locked.Push (std::move (delayed));
120
126
uv_async_send (&flush_tasks_);
121
127
}
122
128
@@ -144,10 +150,12 @@ class WorkerThreadsTaskRunner::DelayedTaskScheduler {
144
150
DelayedTaskScheduler* scheduler =
145
151
ContainerOf (&DelayedTaskScheduler::loop_, flush_tasks->loop );
146
152
147
- std::queue<std::unique_ptr<Task>> tasks_to_run =
148
- scheduler->tasks_ .Lock ().PopAll ();
153
+ auto tasks_to_run = scheduler->tasks_ .Lock ().PopAll ();
149
154
while (!tasks_to_run.empty ()) {
150
- std::unique_ptr<Task> task = std::move (tasks_to_run.front ());
155
+ // We have to use const_cast because std::priority_queue::top() does not
156
+ // return a movable item.
157
+ std::unique_ptr<Task> task =
158
+ std::move (const_cast <std::unique_ptr<Task>&>(tasks_to_run.top ()));
151
159
tasks_to_run.pop ();
152
160
// This runs either the ScheduleTasks that scheduels the timers to
153
161
// pop the tasks back into the worker task runner queue, or the
@@ -177,7 +185,7 @@ class WorkerThreadsTaskRunner::DelayedTaskScheduler {
177
185
class ScheduleTask : public Task {
178
186
public:
179
187
ScheduleTask (DelayedTaskScheduler* scheduler,
180
- std::unique_ptr<Task > task,
188
+ std::unique_ptr<TaskQueueEntry > task,
181
189
double delay_in_seconds)
182
190
: scheduler_(scheduler),
183
191
task_ (std::move(task)),
@@ -194,7 +202,7 @@ class WorkerThreadsTaskRunner::DelayedTaskScheduler {
194
202
195
203
private:
196
204
DelayedTaskScheduler* scheduler_;
197
- std::unique_ptr<Task > task_;
205
+ std::unique_ptr<TaskQueueEntry > task_;
198
206
double delay_in_seconds_;
199
207
};
200
208
@@ -205,20 +213,21 @@ class WorkerThreadsTaskRunner::DelayedTaskScheduler {
205
213
scheduler->TakeTimerTask (timer));
206
214
}
207
215
208
- std::unique_ptr<Task> TakeTimerTask (uv_timer_t * timer) {
209
- std::unique_ptr<Task> task (static_cast <Task*>(timer->data ));
216
+ std::unique_ptr<TaskQueueEntry> TakeTimerTask (uv_timer_t * timer) {
217
+ std::unique_ptr<TaskQueueEntry> task_entry (
218
+ static_cast <TaskQueueEntry*>(timer->data ));
210
219
uv_timer_stop (timer);
211
220
uv_close (reinterpret_cast <uv_handle_t *>(timer), [](uv_handle_t * handle) {
212
221
delete reinterpret_cast <uv_timer_t *>(handle);
213
222
});
214
223
timers_.erase (timer);
215
- return task ;
224
+ return task_entry ;
216
225
}
217
226
218
227
uv_sem_t ready_;
219
228
// Task queue in the worker thread task runner, we push the delayed task back
220
229
// to it when the timer expires.
221
- TaskQueue<Task >* pending_worker_tasks_;
230
+ TaskQueue<TaskQueueEntry >* pending_worker_tasks_;
222
231
223
232
// Locally scheduled tasks to be poped into the worker task runner queue.
224
233
// It is flushed whenever the next closest timer expires.
@@ -264,13 +273,20 @@ WorkerThreadsTaskRunner::WorkerThreadsTaskRunner(
264
273
}
265
274
}
266
275
267
- void WorkerThreadsTaskRunner::PostTask (std::unique_ptr<Task> task) {
268
- pending_worker_tasks_.Lock ().Push (std::move (task));
276
+ void WorkerThreadsTaskRunner::PostTask (v8::TaskPriority priority,
277
+ std::unique_ptr<v8::Task> task,
278
+ const v8::SourceLocation& location) {
279
+ auto entry = std::make_unique<TaskQueueEntry>(std::move (task), priority);
280
+ pending_worker_tasks_.Lock ().Push (std::move (entry));
269
281
}
270
282
271
- void WorkerThreadsTaskRunner::PostDelayedTask (std::unique_ptr<Task> task,
272
- double delay_in_seconds) {
273
- delayed_task_scheduler_->PostDelayedTask (std::move (task), delay_in_seconds);
283
+ void WorkerThreadsTaskRunner::PostDelayedTask (
284
+ v8::TaskPriority priority,
285
+ std::unique_ptr<v8::Task> task,
286
+ const v8::SourceLocation& location,
287
+ double delay_in_seconds) {
288
+ delayed_task_scheduler_->PostDelayedTask (
289
+ priority, std::move (task), delay_in_seconds);
274
290
}
275
291
276
292
void WorkerThreadsTaskRunner::BlockingDrain () {
@@ -330,7 +346,9 @@ void PerIsolatePlatformData::PostTaskImpl(std::unique_ptr<Task> task,
330
346
331
347
auto locked = foreground_tasks_.Lock ();
332
348
if (flush_tasks_ == nullptr ) return ;
333
- locked.Push (std::move (task));
349
+ // All foreground tasks are treated as user blocking tasks.
350
+ locked.Push (std::make_unique<TaskQueueEntry>(
351
+ std::move (task), v8::TaskPriority::kUserBlocking ));
334
352
uv_async_send (flush_tasks_);
335
353
}
336
354
@@ -356,6 +374,8 @@ void PerIsolatePlatformData::PostDelayedTaskImpl(
356
374
delayed->task = std::move (task);
357
375
delayed->platform_data = shared_from_this ();
358
376
delayed->timeout = delay_in_seconds;
377
+ // All foreground tasks are treated as user blocking tasks.
378
+ delayed->priority = v8::TaskPriority::kUserBlocking ;
359
379
locked.Push (std::move (delayed));
360
380
uv_async_send (flush_tasks_);
361
381
}
@@ -562,11 +582,13 @@ void NodePlatform::DrainTasks(Isolate* isolate) {
562
582
bool PerIsolatePlatformData::FlushForegroundTasksInternal () {
563
583
bool did_work = false ;
564
584
565
- std::queue<std::unique_ptr<DelayedTask>> delayed_tasks_to_schedule =
566
- foreground_delayed_tasks_.Lock ().PopAll ();
585
+ auto delayed_tasks_to_schedule = foreground_delayed_tasks_.Lock ().PopAll ();
567
586
while (!delayed_tasks_to_schedule.empty ()) {
587
+ // We have to use const_cast because std::priority_queue::top() does not
588
+ // return a movable item.
568
589
std::unique_ptr<DelayedTask> delayed =
569
- std::move (delayed_tasks_to_schedule.front ());
590
+ std::move (const_cast <std::unique_ptr<DelayedTask>&>(
591
+ delayed_tasks_to_schedule.top ()));
570
592
delayed_tasks_to_schedule.pop ();
571
593
572
594
did_work = true ;
@@ -591,17 +613,20 @@ bool PerIsolatePlatformData::FlushForegroundTasksInternal() {
591
613
});
592
614
}
593
615
594
- std::queue<std::unique_ptr<Task>> tasks;
616
+ TaskQueue<TaskQueueEntry>::PriorityQueue tasks;
595
617
{
596
618
auto locked = foreground_tasks_.Lock ();
597
619
tasks = locked.PopAll ();
598
620
}
599
621
600
622
while (!tasks.empty ()) {
601
- std::unique_ptr<Task> task = std::move (tasks.front ());
623
+ // We have to use const_cast because std::priority_queue::top() does not
624
+ // return a movable item.
625
+ std::unique_ptr<TaskQueueEntry> entry =
626
+ std::move (const_cast <std::unique_ptr<TaskQueueEntry>&>(tasks.top ()));
602
627
tasks.pop ();
603
628
did_work = true ;
604
- RunForegroundTask (std::move (task));
629
+ RunForegroundTask (std::move (entry-> task ));
605
630
}
606
631
607
632
return did_work;
@@ -622,7 +647,7 @@ void NodePlatform::PostTaskOnWorkerThreadImpl(
622
647
}
623
648
fflush (stderr);
624
649
}
625
- worker_thread_task_runner_->PostTask (std::move (task));
650
+ worker_thread_task_runner_->PostTask (priority, std::move (task), location );
626
651
}
627
652
628
653
void NodePlatform::PostDelayedTaskOnWorkerThreadImpl (
@@ -642,8 +667,8 @@ void NodePlatform::PostDelayedTaskOnWorkerThreadImpl(
642
667
}
643
668
fflush (stderr);
644
669
}
645
- worker_thread_task_runner_->PostDelayedTask (std::move (task),
646
- delay_in_seconds);
670
+ worker_thread_task_runner_->PostDelayedTask (
671
+ priority, std::move (task), location, delay_in_seconds);
647
672
}
648
673
649
674
IsolatePlatformDelegate* NodePlatform::ForIsolate (Isolate* isolate) {
@@ -742,7 +767,8 @@ std::unique_ptr<T> TaskQueue<T>::Locked::Pop() {
742
767
if (queue_->task_queue_ .empty ()) {
743
768
return std::unique_ptr<T>(nullptr );
744
769
}
745
- std::unique_ptr<T> result = std::move (queue_->task_queue_ .front ());
770
+ std::unique_ptr<T> result = std::move (
771
+ std::move (const_cast <std::unique_ptr<T>&>(queue_->task_queue_ .top ())));
746
772
queue_->task_queue_ .pop ();
747
773
return result;
748
774
}
@@ -755,7 +781,8 @@ std::unique_ptr<T> TaskQueue<T>::Locked::BlockingPop() {
755
781
if (queue_->stopped_ ) {
756
782
return std::unique_ptr<T>(nullptr );
757
783
}
758
- std::unique_ptr<T> result = std::move (queue_->task_queue_ .front ());
784
+ std::unique_ptr<T> result = std::move (
785
+ std::move (const_cast <std::unique_ptr<T>&>(queue_->task_queue_ .top ())));
759
786
queue_->task_queue_ .pop ();
760
787
return result;
761
788
}
@@ -781,8 +808,8 @@ void TaskQueue<T>::Locked::Stop() {
781
808
}
782
809
783
810
template <class T >
784
- std::queue<std::unique_ptr<T>> TaskQueue<T>::Locked::PopAll() {
785
- std::queue<std::unique_ptr<T>> result;
811
+ TaskQueue<T>::PriorityQueue TaskQueue<T>::Locked::PopAll() {
812
+ TaskQueue<T>::PriorityQueue result;
786
813
result.swap (queue_->task_queue_ );
787
814
return result;
788
815
}
0 commit comments