OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/renderer/scheduler/task_queue_manager.h" | 5 #include "content/renderer/scheduler/task_queue_manager.h" |
6 | 6 |
7 #include <queue> | 7 #include <queue> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/trace_event/trace_event.h" | 10 #include "base/trace_event/trace_event.h" |
(...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
310 TaskQueueManager::TaskRunnerForQueue(size_t queue_index) const { | 310 TaskQueueManager::TaskRunnerForQueue(size_t queue_index) const { |
311 return Queue(queue_index); | 311 return Queue(queue_index); |
312 } | 312 } |
313 | 313 |
314 bool TaskQueueManager::IsQueueEmpty(size_t queue_index) const { | 314 bool TaskQueueManager::IsQueueEmpty(size_t queue_index) const { |
315 internal::TaskQueue* queue = Queue(queue_index); | 315 internal::TaskQueue* queue = Queue(queue_index); |
316 return queue->IsQueueEmpty(); | 316 return queue->IsQueueEmpty(); |
317 } | 317 } |
318 | 318 |
319 void TaskQueueManager::SetAutoPump(size_t queue_index, bool auto_pump) { | 319 void TaskQueueManager::SetAutoPump(size_t queue_index, bool auto_pump) { |
320 main_thread_checker_.CalledOnValidThread(); | 320 DCHECK(main_thread_checker_.CalledOnValidThread()); |
321 internal::TaskQueue* queue = Queue(queue_index); | 321 internal::TaskQueue* queue = Queue(queue_index); |
322 queue->SetAutoPump(auto_pump); | 322 queue->SetAutoPump(auto_pump); |
323 } | 323 } |
324 | 324 |
325 void TaskQueueManager::PumpQueue(size_t queue_index) { | 325 void TaskQueueManager::PumpQueue(size_t queue_index) { |
326 main_thread_checker_.CalledOnValidThread(); | 326 DCHECK(main_thread_checker_.CalledOnValidThread()); |
327 internal::TaskQueue* queue = Queue(queue_index); | 327 internal::TaskQueue* queue = Queue(queue_index); |
328 queue->PumpQueue(); | 328 queue->PumpQueue(); |
329 } | 329 } |
330 | 330 |
331 bool TaskQueueManager::UpdateWorkQueues( | 331 bool TaskQueueManager::UpdateWorkQueues( |
332 base::TimeTicks* next_pending_delayed_task) { | 332 base::TimeTicks* next_pending_delayed_task) { |
333 // TODO(skyostil): This is not efficient when the number of queues grows very | 333 // TODO(skyostil): This is not efficient when the number of queues grows very |
334 // large due to the number of locks taken. Consider optimizing when we get | 334 // large due to the number of locks taken. Consider optimizing when we get |
335 // there. | 335 // there. |
336 main_thread_checker_.CalledOnValidThread(); | 336 DCHECK(main_thread_checker_.CalledOnValidThread()); |
337 bool has_work = false; | 337 bool has_work = false; |
338 for (auto& queue : queues_) { | 338 for (auto& queue : queues_) { |
339 has_work |= queue->UpdateWorkQueue(next_pending_delayed_task); | 339 has_work |= queue->UpdateWorkQueue(next_pending_delayed_task); |
340 if (!queue->work_queue().empty()) { | 340 if (!queue->work_queue().empty()) { |
341 // Currently we should not be getting tasks with delayed run times in any | 341 // Currently we should not be getting tasks with delayed run times in any |
342 // of the work queues. | 342 // of the work queues. |
343 DCHECK(queue->work_queue().front().delayed_run_time.is_null()); | 343 DCHECK(queue->work_queue().front().delayed_run_time.is_null()); |
344 } | 344 } |
345 } | 345 } |
346 return has_work; | 346 return has_work; |
(...skipping 13 matching lines...) Expand all Loading... |
360 main_task_runner_->PostTask( | 360 main_task_runner_->PostTask( |
361 FROM_HERE, Bind(&TaskQueueManager::DoWork, task_queue_manager_weak_ptr_, | 361 FROM_HERE, Bind(&TaskQueueManager::DoWork, task_queue_manager_weak_ptr_, |
362 on_main_thread)); | 362 on_main_thread)); |
363 } | 363 } |
364 | 364 |
365 void TaskQueueManager::DoWork(bool posted_from_main_thread) { | 365 void TaskQueueManager::DoWork(bool posted_from_main_thread) { |
366 if (posted_from_main_thread) { | 366 if (posted_from_main_thread) { |
367 pending_dowork_count_--; | 367 pending_dowork_count_--; |
368 DCHECK_GE(pending_dowork_count_, 0); | 368 DCHECK_GE(pending_dowork_count_, 0); |
369 } | 369 } |
370 main_thread_checker_.CalledOnValidThread(); | 370 DCHECK(main_thread_checker_.CalledOnValidThread()); |
371 | 371 |
372 base::TimeTicks next_pending_delayed_task( | 372 base::TimeTicks next_pending_delayed_task( |
373 base::TimeTicks::FromInternalValue(kMaxTimeTicks)); | 373 base::TimeTicks::FromInternalValue(kMaxTimeTicks)); |
374 for (int i = 0; i < work_batch_size_; i++) { | 374 for (int i = 0; i < work_batch_size_; i++) { |
375 if (!UpdateWorkQueues(&next_pending_delayed_task)) | 375 if (!UpdateWorkQueues(&next_pending_delayed_task)) |
376 return; | 376 return; |
377 | 377 |
378 // Interrupt the work batch if we should run the next delayed task. | 378 // Interrupt the work batch if we should run the next delayed task. |
379 if (i > 0 && next_pending_delayed_task.ToInternalValue() != kMaxTimeTicks && | 379 if (i > 0 && next_pending_delayed_task.ToInternalValue() != kMaxTimeTicks && |
380 Now() >= next_pending_delayed_task) | 380 Now() >= next_pending_delayed_task) |
(...skipping 16 matching lines...) Expand all Loading... |
397 AsValueWithSelectorResult(should_run, *out_queue_index)); | 397 AsValueWithSelectorResult(should_run, *out_queue_index)); |
398 return should_run; | 398 return should_run; |
399 } | 399 } |
400 | 400 |
401 void TaskQueueManager::DidQueueTask(base::PendingTask* pending_task) { | 401 void TaskQueueManager::DidQueueTask(base::PendingTask* pending_task) { |
402 pending_task->sequence_num = task_sequence_num_.GetNext(); | 402 pending_task->sequence_num = task_sequence_num_.GetNext(); |
403 task_annotator_.DidQueueTask("TaskQueueManager::PostTask", *pending_task); | 403 task_annotator_.DidQueueTask("TaskQueueManager::PostTask", *pending_task); |
404 } | 404 } |
405 | 405 |
406 void TaskQueueManager::ProcessTaskFromWorkQueue(size_t queue_index) { | 406 void TaskQueueManager::ProcessTaskFromWorkQueue(size_t queue_index) { |
407 main_thread_checker_.CalledOnValidThread(); | 407 DCHECK(main_thread_checker_.CalledOnValidThread()); |
408 internal::TaskQueue* queue = Queue(queue_index); | 408 internal::TaskQueue* queue = Queue(queue_index); |
409 base::PendingTask pending_task = queue->TakeTaskFromWorkQueue(); | 409 base::PendingTask pending_task = queue->TakeTaskFromWorkQueue(); |
410 if (!pending_task.nestable) { | 410 if (!pending_task.nestable) { |
411 // Defer non-nestable work to the main task runner. NOTE these tasks can be | 411 // Defer non-nestable work to the main task runner. NOTE these tasks can be |
412 // arbitrarily delayed so the additional delay should not be a problem. | 412 // arbitrarily delayed so the additional delay should not be a problem. |
413 main_task_runner_->PostNonNestableTask(pending_task.posted_from, | 413 main_task_runner_->PostNonNestableTask(pending_task.posted_from, |
414 pending_task.task); | 414 pending_task.task); |
415 } else { | 415 } else { |
416 task_annotator_.RunTask("TaskQueueManager::PostTask", | 416 task_annotator_.RunTask("TaskQueueManager::PostTask", |
417 "TaskQueueManager::RunTask", pending_task); | 417 "TaskQueueManager::RunTask", pending_task); |
418 } | 418 } |
419 } | 419 } |
420 | 420 |
421 bool TaskQueueManager::RunsTasksOnCurrentThread() const { | 421 bool TaskQueueManager::RunsTasksOnCurrentThread() const { |
422 return main_task_runner_->RunsTasksOnCurrentThread(); | 422 return main_task_runner_->RunsTasksOnCurrentThread(); |
423 } | 423 } |
424 | 424 |
425 bool TaskQueueManager::PostDelayedTask( | 425 bool TaskQueueManager::PostDelayedTask( |
426 const tracked_objects::Location& from_here, | 426 const tracked_objects::Location& from_here, |
427 const base::Closure& task, | 427 const base::Closure& task, |
428 base::TimeDelta delay) { | 428 base::TimeDelta delay) { |
429 DCHECK(delay > base::TimeDelta()); | 429 DCHECK(delay > base::TimeDelta()); |
430 return main_task_runner_->PostDelayedTask(from_here, task, delay); | 430 return main_task_runner_->PostDelayedTask(from_here, task, delay); |
431 } | 431 } |
432 | 432 |
433 void TaskQueueManager::SetQueueName(size_t queue_index, const char* name) { | 433 void TaskQueueManager::SetQueueName(size_t queue_index, const char* name) { |
434 main_thread_checker_.CalledOnValidThread(); | 434 DCHECK(main_thread_checker_.CalledOnValidThread()); |
435 internal::TaskQueue* queue = Queue(queue_index); | 435 internal::TaskQueue* queue = Queue(queue_index); |
436 queue->set_name(name); | 436 queue->set_name(name); |
437 } | 437 } |
438 | 438 |
439 void TaskQueueManager::SetWorkBatchSize(int work_batch_size) { | 439 void TaskQueueManager::SetWorkBatchSize(int work_batch_size) { |
440 main_thread_checker_.CalledOnValidThread(); | 440 DCHECK(main_thread_checker_.CalledOnValidThread()); |
441 DCHECK_GE(work_batch_size, 1); | 441 DCHECK_GE(work_batch_size, 1); |
442 work_batch_size_ = work_batch_size; | 442 work_batch_size_ = work_batch_size; |
443 } | 443 } |
444 | 444 |
445 void TaskQueueManager::SetTimeSourceForTesting( | 445 void TaskQueueManager::SetTimeSourceForTesting( |
446 scoped_refptr<cc::TestNowSource> time_source) { | 446 scoped_refptr<cc::TestNowSource> time_source) { |
447 main_thread_checker_.CalledOnValidThread(); | 447 DCHECK(main_thread_checker_.CalledOnValidThread()); |
448 time_source_ = time_source; | 448 time_source_ = time_source; |
449 } | 449 } |
450 | 450 |
451 base::TimeTicks TaskQueueManager::Now() const { | 451 base::TimeTicks TaskQueueManager::Now() const { |
452 return UNLIKELY(time_source_) ? time_source_->Now() : base::TimeTicks::Now(); | 452 return UNLIKELY(time_source_) ? time_source_->Now() : base::TimeTicks::Now(); |
453 } | 453 } |
454 | 454 |
455 scoped_refptr<base::debug::ConvertableToTraceFormat> | 455 scoped_refptr<base::debug::ConvertableToTraceFormat> |
456 TaskQueueManager::AsValueWithSelectorResult(bool should_run, | 456 TaskQueueManager::AsValueWithSelectorResult(bool should_run, |
457 size_t selected_queue) const { | 457 size_t selected_queue) const { |
458 main_thread_checker_.CalledOnValidThread(); | 458 DCHECK(main_thread_checker_.CalledOnValidThread()); |
459 scoped_refptr<base::debug::TracedValue> state = | 459 scoped_refptr<base::debug::TracedValue> state = |
460 new base::debug::TracedValue(); | 460 new base::debug::TracedValue(); |
461 state->BeginArray("queues"); | 461 state->BeginArray("queues"); |
462 for (auto& queue : queues_) | 462 for (auto& queue : queues_) |
463 queue->AsValueInto(state.get()); | 463 queue->AsValueInto(state.get()); |
464 state->EndArray(); | 464 state->EndArray(); |
465 state->BeginDictionary("selector"); | 465 state->BeginDictionary("selector"); |
466 selector_->AsValueInto(state.get()); | 466 selector_->AsValueInto(state.get()); |
467 state->EndDictionary(); | 467 state->EndDictionary(); |
468 if (should_run) | 468 if (should_run) |
469 state->SetInteger("selected_queue", selected_queue); | 469 state->SetInteger("selected_queue", selected_queue); |
470 return state; | 470 return state; |
471 } | 471 } |
472 | 472 |
473 } // namespace content | 473 } // namespace content |
OLD | NEW |