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 #ifndef BASE_TASK_SEQUENCE_MANAGER_WORK_QUEUE_H_ 6 #define BASE_TASK_SEQUENCE_MANAGER_WORK_QUEUE_H_ 7 8 #include "base/base_export.h" 9 #include "base/task/sequence_manager/enqueue_order.h" 10 #include "base/task/sequence_manager/intrusive_heap.h" 11 #include "base/task/sequence_manager/sequenced_task_source.h" 12 #include "base/task/sequence_manager/task_queue_impl.h" 13 #include "base/trace_event/trace_event.h" 14 #include "base/trace_event/trace_event_argument.h" 15 16 namespace base { 17 namespace sequence_manager { 18 namespace internal { 19 20 class WorkQueueSets; 21 22 // This class keeps track of immediate and delayed tasks which are due to run 23 // now. It interfaces deeply with WorkQueueSets which keeps track of which queue 24 // (with a given priority) contains the oldest task. 25 // 26 // If a fence is inserted, WorkQueue behaves normally up until 27 // TakeTaskFromWorkQueue reaches or exceeds the fence. At that point it the 28 // API subset used by WorkQueueSets pretends the WorkQueue is empty until the 29 // fence is removed. This functionality is a primitive intended for use by 30 // throttling mechanisms. 31 class BASE_EXPORT WorkQueue { 32 public: 33 using QueueType = internal::TaskQueueImpl::WorkQueueType; 34 35 // Note |task_queue| can be null if queue_type is kNonNestable. 36 WorkQueue(TaskQueueImpl* task_queue, const char* name, QueueType queue_type); 37 ~WorkQueue(); 38 39 // Associates this work queue with the given work queue sets. This must be 40 // called before any tasks can be inserted into this work queue. 41 void AssignToWorkQueueSets(WorkQueueSets* work_queue_sets); 42 43 // Assigns the current set index. 44 void AssignSetIndex(size_t work_queue_set_index); 45 46 void AsValueInto(TimeTicks now, trace_event::TracedValue* state) const; 47 48 // Returns true if the |tasks_| is empty. This method ignores any fences. Empty()49 bool Empty() const { return tasks_.empty(); } 50 51 // If the |tasks_| isn't empty and a fence hasn't been reached, 52 // |enqueue_order| gets set to the enqueue order of the front task and the 53 // function returns true. Otherwise the function returns false. 54 bool GetFrontTaskEnqueueOrder(EnqueueOrder* enqueue_order) const; 55 56 // Returns the first task in this queue or null if the queue is empty. This 57 // method ignores any fences. 58 const TaskQueueImpl::Task* GetFrontTask() const; 59 60 // Returns the last task in this queue or null if the queue is empty. This 61 // method ignores any fences. 62 const TaskQueueImpl::Task* GetBackTask() const; 63 64 // Pushes the task onto the |tasks_| and if a fence hasn't been reached 65 // it informs the WorkQueueSets if the head changed. 66 void Push(TaskQueueImpl::Task task); 67 68 // Pushes the task onto the front of the |tasks_| and if it's before any 69 // fence it informs the WorkQueueSets the head changed. Use with caution this 70 // API can easily lead to task starvation if misused. 71 void PushNonNestableTaskToFront(TaskQueueImpl::Task task); 72 73 // Reloads the empty |tasks_| with 74 // |task_queue_->TakeImmediateIncomingQueue| and if a fence hasn't been 75 // reached it informs the WorkQueueSets if the head changed. 76 void ReloadEmptyImmediateQueue(); 77 Size()78 size_t Size() const { return tasks_.size(); } 79 80 // Pulls a task off the |tasks_| and informs the WorkQueueSets. If the 81 // task removed had an enqueue order >= the current fence then WorkQueue 82 // pretends to be empty as far as the WorkQueueSets is concerned. 83 TaskQueueImpl::Task TakeTaskFromWorkQueue(); 84 85 // Removes all canceled tasks from the head of the list. Returns true if any 86 // tasks were removed. 87 bool RemoveAllCanceledTasksFromFront(); 88 name()89 const char* name() const { return name_; } 90 task_queue()91 TaskQueueImpl* task_queue() const { return task_queue_; } 92 work_queue_sets()93 WorkQueueSets* work_queue_sets() const { return work_queue_sets_; } 94 work_queue_set_index()95 size_t work_queue_set_index() const { return work_queue_set_index_; } 96 heap_handle()97 HeapHandle heap_handle() const { return heap_handle_; } 98 set_heap_handle(HeapHandle handle)99 void set_heap_handle(HeapHandle handle) { heap_handle_ = handle; } 100 queue_type()101 QueueType queue_type() const { return queue_type_; } 102 103 // Returns true if the front task in this queue has an older enqueue order 104 // than the front task of |other_queue|. Both queue are assumed to be 105 // non-empty. This method ignores any fences. 106 bool ShouldRunBefore(const WorkQueue* other_queue) const; 107 108 // Submit a fence. When TakeTaskFromWorkQueue encounters a task whose 109 // enqueue_order is >= |fence| then the WorkQueue will start pretending to be. 110 // empty. 111 // Inserting a fence may supersede a previous one and unblock some tasks. 112 // Returns true if any tasks where unblocked, returns false otherwise. 113 bool InsertFence(EnqueueOrder fence); 114 115 // Submit a fence without triggering a WorkQueueSets notification. 116 // Caller must ensure that WorkQueueSets are properly updated. 117 // This method should not be called when a fence is already present. 118 void InsertFenceSilently(EnqueueOrder fence); 119 120 // Removes any fences that where added and if WorkQueue was pretending to be 121 // empty, then the real value is reported to WorkQueueSets. Returns true if 122 // any tasks where unblocked. 123 bool RemoveFence(); 124 125 // Returns true if any tasks are blocked by the fence. Returns true if the 126 // queue is empty and fence has been set (i.e. future tasks would be blocked). 127 // Otherwise returns false. 128 bool BlockedByFence() const; 129 130 // Test support function. This should not be used in production code. 131 void PopTaskForTesting(); 132 133 private: 134 bool InsertFenceImpl(EnqueueOrder fence); 135 136 TaskQueueImpl::TaskDeque tasks_; 137 WorkQueueSets* work_queue_sets_ = nullptr; // NOT OWNED. 138 TaskQueueImpl* const task_queue_; // NOT OWNED. 139 size_t work_queue_set_index_ = 0; 140 HeapHandle heap_handle_; 141 const char* const name_; 142 EnqueueOrder fence_; 143 const QueueType queue_type_; 144 145 DISALLOW_COPY_AND_ASSIGN(WorkQueue); 146 }; 147 148 } // namespace internal 149 } // namespace sequence_manager 150 } // namespace base 151 152 #endif // BASE_TASK_SEQUENCE_MANAGER_WORK_QUEUE_H_ 153