Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(873)

Unified Diff: third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.h

Issue 2258713004: Make tasks cancellable inside the blink scheduler. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Various comment nits addressed Created 4 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.h
diff --git a/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.h b/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.h
index dee99194ecc13e1a591d5dd47d570827b46de8b4..f56bb3615cd85453575210e901c239369a867bc6 100644
--- a/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.h
+++ b/third_party/WebKit/Source/platform/scheduler/base/task_queue_impl.h
@@ -28,6 +28,32 @@ namespace internal {
class WorkQueue;
class WorkQueueSets;
+// TaskQueueImpl has four main queues:
+//
+// Immediate (non-delayed) tasks:
+// immediate_incoming_queue - PostTask enqueues tasks here
+// immediate_work_queue
+//
+// Delayed tasks
+// delayed_incoming_queue - PostDelayedTask enqueues tasks here
+// delayed_work_queue
+//
+// The immediate_incoming_queue can be accessed from any thread, the other
+// queues are main-thread only. To reduce the overhead of locking,
+// immediate_work_queue is swapped with immediate_incoming_queue when
+// immediate_work_queue becomes empty.
+//
+// Delayed tasks are initially posted to delayed_incoming_queue and a wakeup
+// is scheduled with the TimeDomain. When the delay has elapsed, the TimeDomain
+// calls UpdateDelayedWorkQueue and ready delayed tasks are moved into the
+// delayed_work_queue. Note the EnqueueOrder (used for ordering) for a delayed
+// task is not set until it's moved into the delayed_work_queue.
+//
+// TaskQueueImpl uses the WorkQueueSets and the TaskQueueSelector to implement
+// prioritization. Task selection is done by the TaskQueueSelector and when a
+// queue is selected, it round-robins between the immediate_work_queue and
+// delayed_work_queue. The reason for this is we want to make sure delayed
+// tasks (normally the most common type) don't starve out immediate work.
class BLINK_PLATFORM_EXPORT TaskQueueImpl final : public TaskQueue {
public:
TaskQueueImpl(TaskQueueManager* task_queue_manager,
@@ -52,6 +78,10 @@ class BLINK_PLATFORM_EXPORT TaskQueueImpl final : public TaskQueue {
bool nestable,
EnqueueOrder enqueue_order);
+ // Create a fake Task based on the handle, suitable for using as a search
+ // key.
+ static Task CreateFakeTaskFromHandle(const TaskHandle& handle);
+
EnqueueOrder enqueue_order() const {
#ifndef NDEBUG
DCHECK(enqueue_order_set_);
@@ -71,13 +101,33 @@ class BLINK_PLATFORM_EXPORT TaskQueueImpl final : public TaskQueue {
bool enqueue_order_set() const { return enqueue_order_set_; }
#endif
+ using ComparatorFn = bool (*)(const Task&, const Task&);
+
+ // Tasks are ordered by |delayed_run_time| smallest first then and by
+ // |sequence_num| in case of a tie.
+ class DelayedRunTimeComparator {
+ public:
+ bool operator()(const Task& a, const Task& b) const;
+ };
+
+ // Tasks are ordered by |enqueue_order_| smallest first.
+ static bool EnqueueOrderComparatorFn(const TaskQueueImpl::Task& a,
+ const TaskQueueImpl::Task& b);
+
+ // Tasks are ordered by |delayed_run_time| smallest first then and by
+ // |sequence_num| in case of a tie.
+ static bool DelayedRunTimeComparatorFn(const TaskQueueImpl::Task& a,
+ const TaskQueueImpl::Task& b);
+
private:
#ifndef NDEBUG
bool enqueue_order_set_;
#endif
- // Similar to sequence number, but the |enqueue_order| is set by
- // EnqueueTasksLocked and is not initially defined for delayed tasks until
- // they are enqueued on the |immediate_incoming_queue_|.
+ // Similar to sequence number, but ultimately the |enqueue_order_| is what
+ // the scheduler uses for task ordering. For immediate tasks |enqueue_order|
+ // is set when posted, but for delayed tasks it's not defined until they are
+ // enqueued on the |delayed_work_queue_|. This is because otherwise delayed
+ // tasks could run before an immediate task posted after the delayed task.
EnqueueOrder enqueue_order_;
};
@@ -90,7 +140,11 @@ class BLINK_PLATFORM_EXPORT TaskQueueImpl final : public TaskQueue {
bool PostNonNestableDelayedTask(const tracked_objects::Location& from_here,
const base::Closure& task,
base::TimeDelta delay) override;
-
+ TaskHandle PostCancellableDelayedTask(
+ const tracked_objects::Location& from_here,
+ const base::Closure& task,
+ base::TimeDelta delay) override;
+ bool CancelTask(const TaskHandle& handle) override;
void SetQueueEnabled(bool enabled) override;
bool IsQueueEnabled() const override;
bool IsEmpty() const override;
@@ -108,6 +162,8 @@ class BLINK_PLATFORM_EXPORT TaskQueueImpl final : public TaskQueue {
TimeDomain* GetTimeDomain() const override;
void SetBlameContext(base::trace_event::BlameContext* blame_context) override;
+ bool IsTaskPending(const TaskHandle& handle) const;
+
void UpdateImmediateWorkQueue(bool should_trigger_wakeup,
const Task* previous_task);
void UpdateDelayedWorkQueue(LazyNow* lazy_now,
@@ -162,6 +218,13 @@ class BLINK_PLATFORM_EXPORT TaskQueueImpl final : public TaskQueue {
private:
friend class WorkQueue;
+ // Note both DelayedRunTimeQueue and ComparatorQueue are sets for fast task
+ // cancellation. Typically queue sizes are well under 200 so the overhead of
+ // std::set vs std::priority_queue and std::queue is lost in the noise of
+ // everything else.
+ using DelayedRunTimeQueue = std::set<Task, Task::DelayedRunTimeComparator>;
+ using ComparatorQueue = std::set<Task, Task::ComparatorFn>;
+
enum class TaskType {
NORMAL,
NON_NESTABLE,
@@ -180,7 +243,7 @@ class BLINK_PLATFORM_EXPORT TaskQueueImpl final : public TaskQueue {
PumpPolicy pump_policy;
TimeDomain* time_domain;
- std::queue<Task> immediate_incoming_queue;
+ ComparatorQueue immediate_incoming_queue;
};
struct MainThreadOnly {
@@ -199,7 +262,7 @@ class BLINK_PLATFORM_EXPORT TaskQueueImpl final : public TaskQueue {
std::unique_ptr<WorkQueue> delayed_work_queue;
std::unique_ptr<WorkQueue> immediate_work_queue;
- std::priority_queue<Task> delayed_incoming_queue;
+ DelayedRunTimeQueue delayed_incoming_queue;
base::ObserverList<base::MessageLoop::TaskObserver> task_observers;
size_t set_index;
bool is_enabled;
@@ -258,9 +321,9 @@ class BLINK_PLATFORM_EXPORT TaskQueueImpl final : public TaskQueue {
void PushOntoImmediateIncomingQueueLocked(Task pending_task);
void TraceQueueSize(bool is_locked) const;
- static void QueueAsValueInto(const std::queue<Task>& queue,
+ static void QueueAsValueInto(const ComparatorQueue& queue,
base::trace_event::TracedValue* state);
- static void QueueAsValueInto(const std::priority_queue<Task>& queue,
+ static void QueueAsValueInto(const DelayedRunTimeQueue& queue,
base::trace_event::TracedValue* state);
static void TaskAsValueInto(const Task& task,
base::trace_event::TracedValue* state);

Powered by Google App Engine
This is Rietveld 408576698