summaryrefslogtreecommitdiff
path: root/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h')
-rw-r--r--chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h225
1 files changed, 225 insertions, 0 deletions
diff --git a/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h b/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h
new file mode 100644
index 00000000000..8f39be19b6c
--- /dev/null
+++ b/chromium/third_party/blink/renderer/platform/scheduler/base/task_queue_selector.h
@@ -0,0 +1,225 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_SELECTOR_H_
+#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_SELECTOR_H_
+
+#include <stddef.h>
+
+#include <set>
+
+#include "base/compiler_specific.h"
+#include "base/macros.h"
+#include "base/pending_task.h"
+#include "base/threading/thread_checker.h"
+#include "third_party/blink/renderer/platform/scheduler/base/task_queue_selector_logic.h"
+#include "third_party/blink/renderer/platform/scheduler/base/work_queue_sets.h"
+
+namespace blink {
+namespace scheduler {
+namespace internal {
+
+// TaskQueueSelector is used by the SchedulerHelper to enable prioritization
+// of particular task queues.
+class PLATFORM_EXPORT TaskQueueSelector {
+ public:
+ TaskQueueSelector();
+ ~TaskQueueSelector();
+
+ // Called to register a queue that can be selected. This function is called
+ // on the main thread.
+ void AddQueue(internal::TaskQueueImpl* queue);
+
+ // The specified work will no longer be considered for selection. This
+ // function is called on the main thread.
+ void RemoveQueue(internal::TaskQueueImpl* queue);
+
+ // Make |queue| eligible for selection. This function is called on the main
+ // thread. Must only be called if |queue| is disabled.
+ void EnableQueue(internal::TaskQueueImpl* queue);
+
+ // Disable selection from |queue|. Must only be called if |queue| is enabled.
+ void DisableQueue(internal::TaskQueueImpl* queue);
+
+ // Called get or set the priority of |queue|.
+ void SetQueuePriority(internal::TaskQueueImpl* queue,
+ TaskQueue::QueuePriority priority);
+
+ // Called to choose the work queue from which the next task should be taken
+ // and run. Return true if |out_work_queue| indicates the queue to service or
+ // false to avoid running any task.
+ //
+ // This function is called on the main thread.
+ bool SelectWorkQueueToService(WorkQueue** out_work_queue);
+
+ // Serialize the selector state for tracing.
+ void AsValueInto(base::trace_event::TracedValue* state) const;
+
+ class PLATFORM_EXPORT Observer {
+ public:
+ virtual ~Observer() = default;
+
+ // Called when |queue| transitions from disabled to enabled.
+ virtual void OnTaskQueueEnabled(internal::TaskQueueImpl* queue) = 0;
+ };
+
+ // Called once to set the Observer. This function is called
+ // on the main thread. If |observer| is null, then no callbacks will occur.
+ void SetTaskQueueSelectorObserver(Observer* observer);
+
+ // Returns true if all the enabled work queues are empty. Returns false
+ // otherwise.
+ bool AllEnabledWorkQueuesAreEmpty() const;
+
+ protected:
+ class PLATFORM_EXPORT PrioritizingSelector {
+ public:
+ PrioritizingSelector(TaskQueueSelector* task_queue_selector,
+ const char* name);
+
+ void ChangeSetIndex(internal::TaskQueueImpl* queue,
+ TaskQueue::QueuePriority priority);
+ void AddQueue(internal::TaskQueueImpl* queue,
+ TaskQueue::QueuePriority priority);
+ void RemoveQueue(internal::TaskQueueImpl* queue);
+
+ bool SelectWorkQueueToService(TaskQueue::QueuePriority max_priority,
+ WorkQueue** out_work_queue,
+ bool* out_chose_delayed_over_immediate);
+
+ WorkQueueSets* delayed_work_queue_sets() {
+ return &delayed_work_queue_sets_;
+ }
+ WorkQueueSets* immediate_work_queue_sets() {
+ return &immediate_work_queue_sets_;
+ }
+
+ const WorkQueueSets* delayed_work_queue_sets() const {
+ return &delayed_work_queue_sets_;
+ }
+ const WorkQueueSets* immediate_work_queue_sets() const {
+ return &immediate_work_queue_sets_;
+ }
+
+ bool ChooseOldestWithPriority(TaskQueue::QueuePriority priority,
+ bool* out_chose_delayed_over_immediate,
+ WorkQueue** out_work_queue) const;
+
+#if DCHECK_IS_ON() || !defined(NDEBUG)
+ bool CheckContainsQueueForTest(const internal::TaskQueueImpl* queue) const;
+#endif
+
+ private:
+ bool ChooseOldestImmediateTaskWithPriority(
+ TaskQueue::QueuePriority priority,
+ WorkQueue** out_work_queue) const;
+
+ bool ChooseOldestDelayedTaskWithPriority(TaskQueue::QueuePriority priority,
+ WorkQueue** out_work_queue) const;
+
+ // Return true if |out_queue| contains the queue with the oldest pending
+ // task from the set of queues of |priority|, or false if all queues of that
+ // priority are empty. In addition |out_chose_delayed_over_immediate| is set
+ // to true iff we chose a delayed work queue in favour of an immediate work
+ // queue.
+ bool ChooseOldestImmediateOrDelayedTaskWithPriority(
+ TaskQueue::QueuePriority priority,
+ bool* out_chose_delayed_over_immediate,
+ WorkQueue** out_work_queue) const;
+
+ const TaskQueueSelector* task_queue_selector_;
+ WorkQueueSets delayed_work_queue_sets_;
+ WorkQueueSets immediate_work_queue_sets_;
+
+ DISALLOW_COPY_AND_ASSIGN(PrioritizingSelector);
+ };
+
+ // Return true if |out_queue| contains the queue with the oldest pending task
+ // from the set of queues of |priority|, or false if all queues of that
+ // priority are empty. In addition |out_chose_delayed_over_immediate| is set
+ // to true iff we chose a delayed work queue in favour of an immediate work
+ // queue. This method will force select an immediate task if those are being
+ // starved by delayed tasks.
+ void SetImmediateStarvationCountForTest(size_t immediate_starvation_count);
+
+ PrioritizingSelector* prioritizing_selector_for_test() {
+ return &prioritizing_selector_;
+ }
+
+ private:
+ // Returns the priority which is next after |priority|.
+ static TaskQueue::QueuePriority NextPriority(
+ TaskQueue::QueuePriority priority);
+
+ bool SelectWorkQueueToServiceInternal(WorkQueue** out_work_queue);
+
+ // Called whenever the selector chooses a task queue for execution with the
+ // priority |priority|.
+ void DidSelectQueueWithPriority(TaskQueue::QueuePriority priority,
+ bool chose_delayed_over_immediate);
+
+ // Maximum score to accumulate before high priority tasks are run even in
+ // the presence of highest priority tasks.
+ static const size_t kMaxHighPriorityStarvationScore = 3;
+
+ // Increment to be applied to the high priority starvation score when a task
+ // should have only a small effect on the score. E.g. A number of highest
+ // priority tasks must run before the high priority queue is considered
+ // starved.
+ static const size_t kSmallScoreIncrementForHighPriorityStarvation = 1;
+
+ // Maximum score to accumulate before normal priority tasks are run even in
+ // the presence of higher priority tasks i.e. highest and high priority tasks.
+ static const size_t kMaxNormalPriorityStarvationScore = 5;
+
+ // Increment to be applied to the normal priority starvation score when a task
+ // should have a large effect on the score. E.g Only a few high priority
+ // priority tasks must run before the normal priority queue is considered
+ // starved.
+ static const size_t kLargeScoreIncrementForNormalPriorityStarvation = 2;
+
+ // Increment to be applied to the normal priority starvation score when a task
+ // should have only a small effect on the score. E.g. A number of highest
+ // priority tasks must run before the normal priority queue is considered
+ // starved.
+ static const size_t kSmallScoreIncrementForNormalPriorityStarvation = 1;
+
+ // Maximum score to accumulate before low priority tasks are run even in the
+ // presence of highest, high, or normal priority tasks.
+ static const size_t kMaxLowPriorityStarvationScore = 25;
+
+ // Increment to be applied to the low priority starvation score when a task
+ // should have a large effect on the score. E.g. Only a few normal/high
+ // priority tasks must run before the low priority queue is considered
+ // starved.
+ static const size_t kLargeScoreIncrementForLowPriorityStarvation = 5;
+
+ // Increment to be applied to the low priority starvation score when a task
+ // should have only a small effect on the score. E.g. A lot of highest
+ // priority tasks must run before the low priority queue is considered
+ // starved.
+ static const size_t kSmallScoreIncrementForLowPriorityStarvation = 1;
+
+ // Maximum number of delayed tasks tasks which can be run while there's a
+ // waiting non-delayed task.
+ static const size_t kMaxDelayedStarvationTasks = 3;
+
+ private:
+ base::ThreadChecker main_thread_checker_;
+
+ PrioritizingSelector prioritizing_selector_;
+ size_t immediate_starvation_count_;
+ size_t high_priority_starvation_score_;
+ size_t normal_priority_starvation_score_;
+ size_t low_priority_starvation_score_;
+
+ Observer* task_queue_selector_observer_; // NOT OWNED
+ DISALLOW_COPY_AND_ASSIGN(TaskQueueSelector);
+};
+
+} // namespace internal
+} // namespace scheduler
+} // namespace blink
+
+#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_SCHEDULER_BASE_TASK_QUEUE_SELECTOR_H_