• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/task/sequence_manager/time_domain.h"
6 
7 #include "base/task/sequence_manager/sequence_manager_impl.h"
8 #include "base/task/sequence_manager/task_queue_impl.h"
9 #include "base/task/sequence_manager/work_queue.h"
10 
11 namespace base {
12 namespace sequence_manager {
13 
TimeDomain()14 TimeDomain::TimeDomain() : sequence_manager_(nullptr) {}
15 
~TimeDomain()16 TimeDomain::~TimeDomain() {
17   DCHECK(main_thread_checker_.CalledOnValidThread());
18 }
19 
OnRegisterWithSequenceManager(internal::SequenceManagerImpl * sequence_manager)20 void TimeDomain::OnRegisterWithSequenceManager(
21     internal::SequenceManagerImpl* sequence_manager) {
22   DCHECK(sequence_manager);
23   DCHECK(!sequence_manager_);
24   sequence_manager_ = sequence_manager;
25 }
26 
sequence_manager() const27 SequenceManager* TimeDomain::sequence_manager() const {
28   DCHECK(sequence_manager_);
29   return sequence_manager_;
30 }
31 
32 // TODO(kraynov): https://crbug.com/857101 Consider making an interface
33 // for SequenceManagerImpl which will expose SetNextDelayedDoWork and
34 // MaybeScheduleImmediateWork methods to make the functions below pure-virtual.
35 
SetNextDelayedDoWork(LazyNow * lazy_now,TimeTicks run_time)36 void TimeDomain::SetNextDelayedDoWork(LazyNow* lazy_now, TimeTicks run_time) {
37   sequence_manager_->SetNextDelayedDoWork(lazy_now, run_time);
38 }
39 
RequestDoWork()40 void TimeDomain::RequestDoWork() {
41   sequence_manager_->MaybeScheduleImmediateWork(FROM_HERE);
42 }
43 
UnregisterQueue(internal::TaskQueueImpl * queue)44 void TimeDomain::UnregisterQueue(internal::TaskQueueImpl* queue) {
45   DCHECK(main_thread_checker_.CalledOnValidThread());
46   DCHECK_EQ(queue->GetTimeDomain(), this);
47   LazyNow lazy_now(CreateLazyNow());
48   SetNextWakeUpForQueue(queue, nullopt, &lazy_now);
49 }
50 
SetNextWakeUpForQueue(internal::TaskQueueImpl * queue,Optional<internal::TaskQueueImpl::DelayedWakeUp> wake_up,LazyNow * lazy_now)51 void TimeDomain::SetNextWakeUpForQueue(
52     internal::TaskQueueImpl* queue,
53     Optional<internal::TaskQueueImpl::DelayedWakeUp> wake_up,
54     LazyNow* lazy_now) {
55   DCHECK(main_thread_checker_.CalledOnValidThread());
56   DCHECK_EQ(queue->GetTimeDomain(), this);
57   DCHECK(queue->IsQueueEnabled() || !wake_up);
58 
59   Optional<TimeTicks> previous_wake_up;
60   if (!delayed_wake_up_queue_.empty())
61     previous_wake_up = delayed_wake_up_queue_.Min().wake_up.time;
62 
63   if (wake_up) {
64     // Insert a new wake-up into the heap.
65     if (queue->heap_handle().IsValid()) {
66       // O(log n)
67       delayed_wake_up_queue_.ChangeKey(queue->heap_handle(),
68                                        {wake_up.value(), queue});
69     } else {
70       // O(log n)
71       delayed_wake_up_queue_.insert({wake_up.value(), queue});
72     }
73   } else {
74     // Remove a wake-up from heap if present.
75     if (queue->heap_handle().IsValid())
76       delayed_wake_up_queue_.erase(queue->heap_handle());
77   }
78 
79   Optional<TimeTicks> new_wake_up;
80   if (!delayed_wake_up_queue_.empty())
81     new_wake_up = delayed_wake_up_queue_.Min().wake_up.time;
82 
83   // TODO(kraynov): https://crbug.com/857101 Review the relationship with
84   // SequenceManager's time. Right now it's not an issue since
85   // VirtualTimeDomain doesn't invoke SequenceManager itself.
86 
87   if (new_wake_up) {
88     if (new_wake_up != previous_wake_up) {
89       // Update the wake-up.
90       SetNextDelayedDoWork(lazy_now, new_wake_up.value());
91     }
92   } else {
93     if (previous_wake_up) {
94       // No new wake-up to be set, cancel the previous one.
95       SetNextDelayedDoWork(lazy_now, TimeTicks::Max());
96     }
97   }
98 }
99 
WakeUpReadyDelayedQueues(LazyNow * lazy_now)100 void TimeDomain::WakeUpReadyDelayedQueues(LazyNow* lazy_now) {
101   DCHECK(main_thread_checker_.CalledOnValidThread());
102   // Wake up any queues with pending delayed work.  Note std::multimap stores
103   // the elements sorted by key, so the begin() iterator points to the earliest
104   // queue to wake-up.
105   while (!delayed_wake_up_queue_.empty() &&
106          delayed_wake_up_queue_.Min().wake_up.time <= lazy_now->Now()) {
107     internal::TaskQueueImpl* queue = delayed_wake_up_queue_.Min().queue;
108     queue->WakeUpForDelayedWork(lazy_now);
109   }
110 }
111 
NextScheduledRunTime() const112 Optional<TimeTicks> TimeDomain::NextScheduledRunTime() const {
113   DCHECK(main_thread_checker_.CalledOnValidThread());
114   if (delayed_wake_up_queue_.empty())
115     return nullopt;
116   return delayed_wake_up_queue_.Min().wake_up.time;
117 }
118 
AsValueInto(trace_event::TracedValue * state) const119 void TimeDomain::AsValueInto(trace_event::TracedValue* state) const {
120   state->BeginDictionary();
121   state->SetString("name", GetName());
122   state->SetInteger("registered_delay_count", delayed_wake_up_queue_.size());
123   if (!delayed_wake_up_queue_.empty()) {
124     TimeDelta delay = delayed_wake_up_queue_.Min().wake_up.time - Now();
125     state->SetDouble("next_delay_ms", delay.InMillisecondsF());
126   }
127   AsValueIntoInternal(state);
128   state->EndDictionary();
129 }
130 
AsValueIntoInternal(trace_event::TracedValue * state) const131 void TimeDomain::AsValueIntoInternal(trace_event::TracedValue* state) const {
132   // Can be overriden to trace some additional state.
133 }
134 
135 }  // namespace sequence_manager
136 }  // namespace base
137