1 // Copyright 2018 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 #ifndef BASE_TASK_SEQUENCE_MANAGER_TIME_DOMAIN_H_ 6 #define BASE_TASK_SEQUENCE_MANAGER_TIME_DOMAIN_H_ 7 8 #include <map> 9 10 #include "base/callback.h" 11 #include "base/logging.h" 12 #include "base/macros.h" 13 #include "base/task/sequence_manager/intrusive_heap.h" 14 #include "base/task/sequence_manager/lazy_now.h" 15 #include "base/task/sequence_manager/task_queue_impl.h" 16 #include "base/time/time.h" 17 18 namespace base { 19 namespace sequence_manager { 20 21 class SequenceManager; 22 23 namespace internal { 24 class SequenceManagerImpl; 25 class TaskQueueImpl; 26 } // namespace internal 27 28 // TimeDomain wakes up TaskQueues when their delayed tasks are due to run. 29 // This class allows overrides to enable clock overriding on some TaskQueues 30 // (e.g. auto-advancing virtual time, throttled clock, etc). 31 // 32 // TaskQueue maintains its own next wake-up time and communicates it 33 // to the TimeDomain, which aggregates wake-ups across registered TaskQueues 34 // into a global wake-up, which ultimately gets passed to the ThreadController. 35 class BASE_EXPORT TimeDomain { 36 public: 37 virtual ~TimeDomain(); 38 39 // Returns LazyNow in TimeDomain's time. 40 // Can be called from any thread. 41 // TODO(alexclarke): Make this main thread only. 42 virtual LazyNow CreateLazyNow() const = 0; 43 44 // Evaluates TimeDomain's time. 45 // Can be called from any thread. 46 // TODO(alexclarke): Make this main thread only. 47 virtual TimeTicks Now() const = 0; 48 49 // Computes the delay until the time when TimeDomain needs to wake up 50 // some TaskQueue. Specific time domains (e.g. virtual or throttled) may 51 // return TimeDelata() if TaskQueues have any delayed tasks they deem 52 // eligible to run. It's also allowed to advance time domains's internal 53 // clock when this method is called. 54 // Can be called from main thread only. 55 // NOTE: |lazy_now| and the return value are in the SequenceManager's time. 56 virtual Optional<TimeDelta> DelayTillNextTask(LazyNow* lazy_now) = 0; 57 58 void AsValueInto(trace_event::TracedValue* state) const; 59 60 protected: 61 TimeDomain(); 62 63 SequenceManager* sequence_manager() const; 64 65 // Returns the earliest scheduled wake up in the TimeDomain's time. 66 Optional<TimeTicks> NextScheduledRunTime() const; 67 NumberOfScheduledWakeUps()68 size_t NumberOfScheduledWakeUps() const { 69 return delayed_wake_up_queue_.size(); 70 } 71 72 // Tells SequenceManager to schedule delayed work, use TimeTicks::Max() 73 // to unschedule. Also cancels any previous requests. 74 // May be overriden to control wake ups manually. 75 virtual void SetNextDelayedDoWork(LazyNow* lazy_now, TimeTicks run_time); 76 77 // Tells SequenceManager to schedule immediate work. 78 // May be overriden to control wake ups manually. 79 virtual void RequestDoWork(); 80 81 // For implementation-specific tracing. 82 virtual void AsValueIntoInternal(trace_event::TracedValue* state) const; 83 virtual const char* GetName() const = 0; 84 85 private: 86 friend class internal::TaskQueueImpl; 87 friend class internal::SequenceManagerImpl; 88 friend class TestTimeDomain; 89 90 // Called when the TimeDomain is registered. 91 // TODO(kraynov): Pass SequenceManager in the constructor. 92 void OnRegisterWithSequenceManager( 93 internal::SequenceManagerImpl* sequence_manager); 94 95 // Schedule TaskQueue to wake up at certain time, repeating calls with 96 // the same |queue| invalidate previous requests. 97 // Nullopt |wake_up| cancels a previously set wake up for |queue|. 98 // NOTE: |lazy_now| is provided in TimeDomain's time. 99 void SetNextWakeUpForQueue( 100 internal::TaskQueueImpl* queue, 101 Optional<internal::TaskQueueImpl::DelayedWakeUp> wake_up, 102 LazyNow* lazy_now); 103 104 // Remove the TaskQueue from any internal data sctructures. 105 void UnregisterQueue(internal::TaskQueueImpl* queue); 106 107 // Wake up each TaskQueue where the delay has elapsed. 108 void WakeUpReadyDelayedQueues(LazyNow* lazy_now); 109 110 struct ScheduledDelayedWakeUp { 111 internal::TaskQueueImpl::DelayedWakeUp wake_up; 112 internal::TaskQueueImpl* queue; 113 114 bool operator<=(const ScheduledDelayedWakeUp& other) const { 115 return wake_up <= other.wake_up; 116 } 117 SetHeapHandleScheduledDelayedWakeUp118 void SetHeapHandle(internal::HeapHandle handle) { 119 DCHECK(handle.IsValid()); 120 queue->set_heap_handle(handle); 121 } 122 ClearHeapHandleScheduledDelayedWakeUp123 void ClearHeapHandle() { 124 DCHECK(queue->heap_handle().IsValid()); 125 queue->set_heap_handle(internal::HeapHandle()); 126 } 127 }; 128 129 internal::SequenceManagerImpl* sequence_manager_; // Not owned. 130 internal::IntrusiveHeap<ScheduledDelayedWakeUp> delayed_wake_up_queue_; 131 132 ThreadChecker main_thread_checker_; 133 DISALLOW_COPY_AND_ASSIGN(TimeDomain); 134 }; 135 136 } // namespace sequence_manager 137 } // namespace base 138 139 #endif // BASE_TASK_SEQUENCE_MANAGER_TIME_DOMAIN_H_ 140