1ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Copyright 2013 The Chromium Authors. All rights reserved. 2ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// Use of this source code is governed by a BSD-style license that can be 3ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch// found in the LICENSE file. 4ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 5ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/incoming_task_queue.h" 6ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 7ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/location.h" 8ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h" 9ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/synchronization/waitable_event.h" 101320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "base/time/time.h" 11ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 12ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochnamespace base { 13ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochnamespace internal { 14ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 15ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochIncomingTaskQueue::IncomingTaskQueue(MessageLoop* message_loop) 161320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci : high_res_task_count_(0), 171320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci message_loop_(message_loop), 18ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch next_sequence_num_(0) { 19ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 20ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 21ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbool IncomingTaskQueue::AddToIncomingQueue( 22ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const tracked_objects::Location& from_here, 23ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const Closure& task, 24ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch TimeDelta delay, 25ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch bool nestable) { 26ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch AutoLock locked(incoming_queue_lock_); 27ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch PendingTask pending_task( 28ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch from_here, task, CalculateDelayedRuntime(delay), nestable); 291320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#if defined(OS_WIN) 301320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // We consider the task needs a high resolution timer if the delay is 311320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // more than 0 and less than 32ms. This caps the relative error to 321320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // less than 50% : a 33ms wait can wake at 48ms since the default 331320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // resolution on Windows is between 10 and 15ms. 341320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (delay > TimeDelta() && 351320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci delay.InMilliseconds() < (2 * Time::kMinLowResolutionThresholdMs)) { 361320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci ++high_res_task_count_; 371320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci pending_task.is_high_res = true; 381320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci } 391320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#endif 40ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return PostPendingTask(&pending_task); 41ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 42ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 431320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tuccibool IncomingTaskQueue::HasHighResolutionTasks() { 441320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci AutoLock lock(incoming_queue_lock_); 451320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return high_res_task_count_ > 0; 46ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 47ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 48ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbool IncomingTaskQueue::IsIdleForTesting() { 49ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch AutoLock lock(incoming_queue_lock_); 50ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return incoming_queue_.empty(); 51ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 52ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 531320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucciint IncomingTaskQueue::ReloadWorkQueue(TaskQueue* work_queue) { 54ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Make sure no tasks are lost. 55ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(work_queue->empty()); 56ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 57ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Acquire all we can from the inter-thread queue with one lock acquisition. 58ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch AutoLock lock(incoming_queue_lock_); 59ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!incoming_queue_.empty()) 601320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci incoming_queue_.Swap(work_queue); 61ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 621320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // Reset the count of high resolution tasks since our queue is now empty. 631320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci int high_res_tasks = high_res_task_count_; 641320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci high_res_task_count_ = 0; 651320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci return high_res_tasks; 66ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 67ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 68ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid IncomingTaskQueue::WillDestroyCurrentMessageLoop() { 69ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch AutoLock lock(incoming_queue_lock_); 70ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch message_loop_ = NULL; 71ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 72ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 73ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochIncomingTaskQueue::~IncomingTaskQueue() { 74ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Verify that WillDestroyCurrentMessageLoop() has been called. 75ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(!message_loop_); 76ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 77ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 78ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTimeTicks IncomingTaskQueue::CalculateDelayedRuntime(TimeDelta delay) { 79ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch TimeTicks delayed_run_time; 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (delay > TimeDelta()) 81ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch delayed_run_time = TimeTicks::Now() + delay; 821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci else 83ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(delay.InMilliseconds(), 0) << "delay should not be negative"; 84ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return delayed_run_time; 85ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 86ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 87ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbool IncomingTaskQueue::PostPendingTask(PendingTask* pending_task) { 88ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Warning: Don't try to short-circuit, and handle this thread's tasks more 89ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // directly, as it could starve handling of foreign threads. Put every task 90ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // into this queue. 91ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 92ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // This should only be called while the lock is taken. 93ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch incoming_queue_lock_.AssertAcquired(); 94ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 95ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!message_loop_) { 96ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch pending_task->task.Reset(); 97ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return false; 98ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 99ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 100ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Initialize the sequence number. The sequence number is used for delayed 101ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // tasks (to faciliate FIFO sorting when two tasks have the same 102ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // delayed_run_time value) and for identifying the task in about:tracing. 103ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch pending_task->sequence_num = next_sequence_num_++; 104ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 1056e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) message_loop_->task_annotator()->DidQueueTask("MessageLoop::PostTask", 1066e8cce623b6e4fe0c9e4af605d675dd9d0338c38Torne (Richard Coles) *pending_task); 107ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 108ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch bool was_empty = incoming_queue_.empty(); 109ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch incoming_queue_.push(*pending_task); 110ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch pending_task->task.Reset(); 111ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 112ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Wake up the pump. 113ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch message_loop_->ScheduleWork(was_empty); 114ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 115ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return true; 116ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 117ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 118ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} // namespace internal 119ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} // namespace base 120