| OLD | NEW | 
 | (Empty) | 
|    1 // Copyright 2014 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 CONTENT_RENDERER_SCHEDULER_TASK_QUEUE_MANAGER_H_ |  | 
|    6 #define CONTENT_RENDERER_SCHEDULER_TASK_QUEUE_MANAGER_H_ |  | 
|    7  |  | 
|    8 #include "base/atomic_sequence_num.h" |  | 
|    9 #include "base/debug/task_annotator.h" |  | 
|   10 #include "base/macros.h" |  | 
|   11 #include "base/memory/weak_ptr.h" |  | 
|   12 #include "base/message_loop/message_loop.h" |  | 
|   13 #include "base/pending_task.h" |  | 
|   14 #include "base/single_thread_task_runner.h" |  | 
|   15 #include "base/synchronization/lock.h" |  | 
|   16 #include "base/threading/thread_checker.h" |  | 
|   17 #include "content/common/content_export.h" |  | 
|   18  |  | 
|   19 namespace base { |  | 
|   20 namespace trace_event { |  | 
|   21 class ConvertableToTraceFormat; |  | 
|   22 class TracedValue; |  | 
|   23 } |  | 
|   24 } |  | 
|   25  |  | 
|   26 namespace cc { |  | 
|   27 class TestNowSource; |  | 
|   28 } |  | 
|   29  |  | 
|   30 namespace content { |  | 
|   31 namespace internal { |  | 
|   32 class LazyNow; |  | 
|   33 class TaskQueue; |  | 
|   34 } |  | 
|   35 class TaskQueueSelector; |  | 
|   36 class NestableSingleThreadTaskRunner; |  | 
|   37  |  | 
|   38 // The task queue manager provides N task queues and a selector interface for |  | 
|   39 // choosing which task queue to service next. Each task queue consists of two |  | 
|   40 // sub queues: |  | 
|   41 // |  | 
|   42 // 1. Incoming task queue. Tasks that are posted get immediately appended here. |  | 
|   43 //    When a task is appended into an empty incoming queue, the task manager |  | 
|   44 //    work function (DoWork) is scheduled to run on the main task runner. |  | 
|   45 // |  | 
|   46 // 2. Work queue. If a work queue is empty when DoWork() is entered, tasks from |  | 
|   47 //    the incoming task queue (if any) are moved here. The work queues are |  | 
|   48 //    registered with the selector as input to the scheduling decision. |  | 
|   49 // |  | 
|   50 class CONTENT_EXPORT TaskQueueManager { |  | 
|   51  public: |  | 
|   52   // Keep TaskQueue::PumpPolicyToString in sync with this enum. |  | 
|   53   enum class PumpPolicy { |  | 
|   54     // Tasks posted to an incoming queue with an AUTO pump policy will be |  | 
|   55     // automatically scheduled for execution or transferred to the work queue |  | 
|   56     // automatically. |  | 
|   57     AUTO, |  | 
|   58     // Tasks posted to an incoming queue with an AFTER_WAKEUP pump policy |  | 
|   59     // will be scheduled for execution or transferred to the work queue |  | 
|   60     // automatically but only after another queue has executed a task. |  | 
|   61     AFTER_WAKEUP, |  | 
|   62     // Tasks posted to an incoming queue with a MANUAL will not be |  | 
|   63     // automatically scheduled for execution or transferred to the work queue. |  | 
|   64     // Instead, the selector should call PumpQueue() when necessary to bring |  | 
|   65     // in new tasks for execution. |  | 
|   66     MANUAL |  | 
|   67   }; |  | 
|   68  |  | 
|   69   // Create a task queue manager with |task_queue_count| task queues. |  | 
|   70   // |main_task_runner| identifies the thread on which where the tasks are |  | 
|   71   // eventually run. |selector| is used to choose which task queue to service. |  | 
|   72   // It should outlive this class. |  | 
|   73   TaskQueueManager( |  | 
|   74       size_t task_queue_count, |  | 
|   75       scoped_refptr<NestableSingleThreadTaskRunner> main_task_runner, |  | 
|   76       TaskQueueSelector* selector); |  | 
|   77   ~TaskQueueManager(); |  | 
|   78  |  | 
|   79   // Returns the task runner which targets the queue selected by |queue_index|. |  | 
|   80   scoped_refptr<base::SingleThreadTaskRunner> TaskRunnerForQueue( |  | 
|   81       size_t queue_index) const; |  | 
|   82  |  | 
|   83   // Sets the pump policy for the |queue_index| to |pump_policy|. By |  | 
|   84   // default queues are created with AUTO_PUMP_POLICY. |  | 
|   85   void SetPumpPolicy(size_t queue_index, PumpPolicy pump_policy); |  | 
|   86  |  | 
|   87   // Reloads new tasks from the incoming queue for |queue_index| into the work |  | 
|   88   // queue, regardless of whether the work queue is empty or not. After this, |  | 
|   89   // this function ensures that the tasks in the work queue, if any, are |  | 
|   90   // scheduled for execution. |  | 
|   91   // |  | 
|   92   // This function only needs to be called if automatic pumping is disabled |  | 
|   93   // for |queue_index|. See |SetQueueAutoPumpPolicy|. By default automatic |  | 
|   94   // pumping is enabled for all queues. |  | 
|   95   void PumpQueue(size_t queue_index); |  | 
|   96  |  | 
|   97   // Returns true if there no tasks in either the work or incoming task queue |  | 
|   98   // identified by |queue_index|. Note that this function involves taking a |  | 
|   99   // lock, so calling it has some overhead. |  | 
|  100   bool IsQueueEmpty(size_t queue_index) const; |  | 
|  101  |  | 
|  102   // Returns the time of the next pending delayed task in any queue.  Ignores |  | 
|  103   // any delayed tasks whose delay has expired. Returns a null TimeTicks object |  | 
|  104   // if no tasks are pending.  NOTE this is somewhat expensive since every queue |  | 
|  105   // will get locked. |  | 
|  106   base::TimeTicks NextPendingDelayedTaskRunTime(); |  | 
|  107  |  | 
|  108   // Set the name |queue_index| for tracing purposes. |name| must be a pointer |  | 
|  109   // to a static string. |  | 
|  110   void SetQueueName(size_t queue_index, const char* name); |  | 
|  111  |  | 
|  112   // Set the number of tasks executed in a single invocation of the task queue |  | 
|  113   // manager. Increasing the batch size can reduce the overhead of yielding |  | 
|  114   // back to the main message loop -- at the cost of potentially delaying other |  | 
|  115   // tasks posted to the main loop. The batch size is 1 by default. |  | 
|  116   void SetWorkBatchSize(int work_batch_size); |  | 
|  117  |  | 
|  118   // These functions can only be called on the same thread that the task queue |  | 
|  119   // manager executes its tasks on. |  | 
|  120   void AddTaskObserver(base::MessageLoop::TaskObserver* task_observer); |  | 
|  121   void RemoveTaskObserver(base::MessageLoop::TaskObserver* task_observer); |  | 
|  122  |  | 
|  123   void SetTimeSourceForTesting(scoped_refptr<cc::TestNowSource> time_source); |  | 
|  124  |  | 
|  125  private: |  | 
|  126   friend class internal::LazyNow; |  | 
|  127   friend class internal::TaskQueue; |  | 
|  128  |  | 
|  129   // Called by the task queue to register a new pending task and allocate a |  | 
|  130   // sequence number for it. |  | 
|  131   void DidQueueTask(base::PendingTask* pending_task); |  | 
|  132  |  | 
|  133   // Post a task to call DoWork() on the main task runner.  Only one pending |  | 
|  134   // DoWork is allowed from the main thread, to prevent an explosion of pending |  | 
|  135   // DoWorks. |  | 
|  136   void MaybePostDoWorkOnMainRunner(); |  | 
|  137  |  | 
|  138   // Use the selector to choose a pending task and run it. |  | 
|  139   void DoWork(bool posted_from_main_thread); |  | 
|  140  |  | 
|  141   // Delayed Tasks with run_times <= Now() are enqueued onto the work queue. |  | 
|  142   // Reloads any empty work queues which have automatic pumping enabled and |  | 
|  143   // which are eligible to be auto pumped based on the |previous_task| which was |  | 
|  144   // run. Call with an empty |previous_task| if no task was just run. Returns |  | 
|  145   // true if any work queue has tasks after doing this. |  | 
|  146   // |next_pending_delayed_task| should be the time of the next known delayed |  | 
|  147   // task. It is updated if any task is found which should run earlier. |  | 
|  148   bool UpdateWorkQueues(const base::PendingTask* previous_task); |  | 
|  149  |  | 
|  150   // Chooses the next work queue to service. Returns true if |out_queue_index| |  | 
|  151   // indicates the queue from which the next task should be run, false to |  | 
|  152   // avoid running any tasks. |  | 
|  153   bool SelectWorkQueueToService(size_t* out_queue_index); |  | 
|  154  |  | 
|  155   // Runs a single nestable task from the work queue designated by |  | 
|  156   // |queue_index|. If |has_previous_task| is true, |previous_task| should |  | 
|  157   // contain the previous task in this work batch. Non-nestable task are |  | 
|  158   // reposted on the run loop. The queue must not be empty. |  | 
|  159   void ProcessTaskFromWorkQueue(size_t queue_index, |  | 
|  160                                 bool has_previous_task, |  | 
|  161                                 base::PendingTask* previous_task); |  | 
|  162  |  | 
|  163   bool RunsTasksOnCurrentThread() const; |  | 
|  164   bool PostDelayedTask(const tracked_objects::Location& from_here, |  | 
|  165                        const base::Closure& task, |  | 
|  166                        base::TimeDelta delay); |  | 
|  167   bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here, |  | 
|  168                                   const base::Closure& task, |  | 
|  169                                   base::TimeDelta delay); |  | 
|  170   internal::TaskQueue* Queue(size_t queue_index) const; |  | 
|  171  |  | 
|  172   base::TimeTicks Now() const; |  | 
|  173  |  | 
|  174   scoped_refptr<base::trace_event::ConvertableToTraceFormat> |  | 
|  175   AsValueWithSelectorResult(bool should_run, size_t selected_queue) const; |  | 
|  176  |  | 
|  177   std::vector<scoped_refptr<internal::TaskQueue>> queues_; |  | 
|  178   base::AtomicSequenceNumber task_sequence_num_; |  | 
|  179   base::debug::TaskAnnotator task_annotator_; |  | 
|  180  |  | 
|  181   base::ThreadChecker main_thread_checker_; |  | 
|  182   scoped_refptr<NestableSingleThreadTaskRunner> main_task_runner_; |  | 
|  183   TaskQueueSelector* selector_; |  | 
|  184  |  | 
|  185   base::WeakPtr<TaskQueueManager> task_queue_manager_weak_ptr_; |  | 
|  186  |  | 
|  187   // The pending_dowork_count_ is only tracked on the main thread since that's |  | 
|  188   // where re-entrant problems happen. |  | 
|  189   int pending_dowork_count_; |  | 
|  190  |  | 
|  191   int work_batch_size_; |  | 
|  192  |  | 
|  193   scoped_refptr<cc::TestNowSource> time_source_; |  | 
|  194  |  | 
|  195   ObserverList<base::MessageLoop::TaskObserver> task_observers_; |  | 
|  196  |  | 
|  197   base::WeakPtrFactory<TaskQueueManager> weak_factory_; |  | 
|  198  |  | 
|  199   DISALLOW_COPY_AND_ASSIGN(TaskQueueManager); |  | 
|  200 }; |  | 
|  201  |  | 
|  202 }  // namespace content |  | 
|  203  |  | 
|  204 #endif  // CONTENT_RENDERER_SCHEDULER_TASK_QUEUE_MANAGER_H_ |  | 
| OLD | NEW |