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/debug/trace_event.h" 8ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/location.h" 9ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/message_loop/message_loop.h" 10ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#include "base/synchronization/waitable_event.h" 11ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 12ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochnamespace base { 13ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochnamespace internal { 14ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 15ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochIncomingTaskQueue::IncomingTaskQueue(MessageLoop* message_loop) 16ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch : message_loop_(message_loop), 17ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch next_sequence_num_(0) { 18ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 19ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 20ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbool IncomingTaskQueue::AddToIncomingQueue( 21ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const tracked_objects::Location& from_here, 22ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const Closure& task, 23ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch TimeDelta delay, 24ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch bool nestable) { 25ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch AutoLock locked(incoming_queue_lock_); 26ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch PendingTask pending_task( 27ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch from_here, task, CalculateDelayedRuntime(delay), nestable); 28ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return PostPendingTask(&pending_task); 29ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 30ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 31ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbool IncomingTaskQueue::TryAddToIncomingQueue( 32ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const tracked_objects::Location& from_here, 33ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch const Closure& task) { 34ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!incoming_queue_lock_.Try()) { 35ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Reset |task|. 36ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch Closure local_task = task; 37ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return false; 38ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 39ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 40ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch AutoLock locked(incoming_queue_lock_, AutoLock::AlreadyAcquired()); 41ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch PendingTask pending_task( 42ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch from_here, task, CalculateDelayedRuntime(TimeDelta()), true); 43ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return PostPendingTask(&pending_task); 44ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 45ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 46ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbool IncomingTaskQueue::IsHighResolutionTimerEnabledForTesting() { 47ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#if defined(OS_WIN) 48ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return !high_resolution_timer_expiration_.is_null(); 49ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#else 50ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return true; 51ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#endif 52ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 53ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 54ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbool IncomingTaskQueue::IsIdleForTesting() { 55ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch AutoLock lock(incoming_queue_lock_); 56ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return incoming_queue_.empty(); 57ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 58ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 59ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid IncomingTaskQueue::LockWaitUnLockForTesting(WaitableEvent* caller_wait, 60ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch WaitableEvent* caller_signal) { 61ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch AutoLock lock(incoming_queue_lock_); 62ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch caller_wait->Signal(); 63ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch caller_signal->Wait(); 64ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 65ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 66ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid IncomingTaskQueue::ReloadWorkQueue(TaskQueue* work_queue) { 67ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Make sure no tasks are lost. 68ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(work_queue->empty()); 69ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 70ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Acquire all we can from the inter-thread queue with one lock acquisition. 71ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch AutoLock lock(incoming_queue_lock_); 72ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!incoming_queue_.empty()) 73ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch incoming_queue_.Swap(work_queue); // Constant time 74ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 75ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(incoming_queue_.empty()); 76ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 77ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 78ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochvoid IncomingTaskQueue::WillDestroyCurrentMessageLoop() { 79ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#if defined(OS_WIN) 80ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // If we left the high-resolution timer activated, deactivate it now. 81ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Doing this is not-critical, it is mainly to make sure we track 82ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // the high resolution timer activations properly in our unit tests. 83ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!high_resolution_timer_expiration_.is_null()) { 84ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch Time::ActivateHighResolutionTimer(false); 85ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch high_resolution_timer_expiration_ = TimeTicks(); 86ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 87ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#endif 88ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 89ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch AutoLock lock(incoming_queue_lock_); 90ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch message_loop_ = NULL; 91ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 92ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 93ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochIncomingTaskQueue::~IncomingTaskQueue() { 94ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Verify that WillDestroyCurrentMessageLoop() has been called. 95ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK(!message_loop_); 96ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 97ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 98ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben MurdochTimeTicks IncomingTaskQueue::CalculateDelayedRuntime(TimeDelta delay) { 99ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch TimeTicks delayed_run_time; 100ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (delay > TimeDelta()) { 101ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch delayed_run_time = TimeTicks::Now() + delay; 102ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 103ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#if defined(OS_WIN) 104ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (high_resolution_timer_expiration_.is_null()) { 105ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Windows timers are granular to 15.6ms. If we only set high-res 106ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // timers for those under 15.6ms, then a 18ms timer ticks at ~32ms, 107ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // which as a percentage is pretty inaccurate. So enable high 108ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // res timers for any timer which is within 2x of the granularity. 109ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // This is a tradeoff between accuracy and power management. 110ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch bool needs_high_res_timers = delay.InMilliseconds() < 111ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch (2 * Time::kMinLowResolutionThresholdMs); 112ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (needs_high_res_timers) { 113ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (Time::ActivateHighResolutionTimer(true)) { 114ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch high_resolution_timer_expiration_ = TimeTicks::Now() + 115ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch TimeDelta::FromMilliseconds( 116ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch MessageLoop::kHighResolutionTimerModeLeaseTimeMs); 117ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 118ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 119ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 120ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#endif 121ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } else { 122ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch DCHECK_EQ(delay.InMilliseconds(), 0) << "delay should not be negative"; 123ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 124ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 125ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#if defined(OS_WIN) 126ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!high_resolution_timer_expiration_.is_null()) { 127ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (TimeTicks::Now() > high_resolution_timer_expiration_) { 128ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch Time::ActivateHighResolutionTimer(false); 129ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch high_resolution_timer_expiration_ = TimeTicks(); 130ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 131ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 132ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch#endif 133ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 134ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return delayed_run_time; 135ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 136ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 137ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdochbool IncomingTaskQueue::PostPendingTask(PendingTask* pending_task) { 138ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Warning: Don't try to short-circuit, and handle this thread's tasks more 139ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // directly, as it could starve handling of foreign threads. Put every task 140ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // into this queue. 141ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 142ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // This should only be called while the lock is taken. 143ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch incoming_queue_lock_.AssertAcquired(); 144ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 145ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch if (!message_loop_) { 146ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch pending_task->task.Reset(); 147ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return false; 148ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch } 149ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 150ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Initialize the sequence number. The sequence number is used for delayed 151ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // tasks (to faciliate FIFO sorting when two tasks have the same 152ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // delayed_run_time value) and for identifying the task in about:tracing. 153ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch pending_task->sequence_num = next_sequence_num_++; 154ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 155ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch TRACE_EVENT_FLOW_BEGIN0("task", "MessageLoop::PostTask", 156ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch TRACE_ID_MANGLE(message_loop_->GetTaskTraceID(*pending_task))); 157ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 158ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch bool was_empty = incoming_queue_.empty(); 159ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch incoming_queue_.push(*pending_task); 160ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch pending_task->task.Reset(); 161ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 162ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch // Wake up the pump. 163ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch message_loop_->ScheduleWork(was_empty); 164ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 165ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch return true; 166ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} 167ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch 168ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} // namespace internal 169ca12bfac764ba476d6cd062bf1dde12cc64c3f40Ben Murdoch} // namespace base 170