Home | History | Annotate | Download | only in sequence_manager
      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.
     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 
     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 
     89   const char* name() const { return name_; }
     90 
     91   TaskQueueImpl* task_queue() const { return task_queue_; }
     92 
     93   WorkQueueSets* work_queue_sets() const { return work_queue_sets_; }
     94 
     95   size_t work_queue_set_index() const { return work_queue_set_index_; }
     96 
     97   HeapHandle heap_handle() const { return heap_handle_; }
     98 
     99   void set_heap_handle(HeapHandle handle) { heap_handle_ = handle; }
    100 
    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