// Copyright 2018 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 BASE_TASK_SEQUENCE_MANAGER_TASKS_H_ #define BASE_TASK_SEQUENCE_MANAGER_TASKS_H_ #include "base/pending_task.h" #include "base/sequenced_task_runner.h" #include "base/task/sequence_manager/enqueue_order.h" namespace base { namespace sequence_manager { using TaskType = uint8_t; constexpr TaskType kTaskTypeNone = 0; namespace internal { enum class WakeUpResolution { kLow, kHigh }; // Wrapper around PostTask method arguments and the assigned task type. // Eventually it becomes a PendingTask once accepted by a TaskQueueImpl. struct BASE_EXPORT PostedTask { explicit PostedTask(scoped_refptr task_runner, OnceClosure callback = OnceClosure(), Location location = Location(), TimeDelta delay = TimeDelta(), Nestable nestable = Nestable::kNestable, TaskType task_type = kTaskTypeNone); PostedTask(PostedTask&& move_from) noexcept; ~PostedTask(); OnceClosure callback; Location location; TimeDelta delay; Nestable nestable; TaskType task_type; // The task runner this task is running on. Can be used by task runners that // support posting back to the "current sequence". scoped_refptr task_runner; // The time at which the task was queued. TimeTicks queue_time; DISALLOW_COPY_AND_ASSIGN(PostedTask); }; // Represents a time at which a task wants to run. Tasks scheduled for the // same point in time will be ordered by their sequence numbers. struct DelayedWakeUp { TimeTicks time; int sequence_num; bool operator!=(const DelayedWakeUp& other) const { return time != other.time || other.sequence_num != sequence_num; } bool operator==(const DelayedWakeUp& other) const { return !(*this != other); } bool operator<=(const DelayedWakeUp& other) const { if (time == other.time) { // Debug gcc builds can compare an element against itself. DCHECK(sequence_num != other.sequence_num || this == &other); // |sequence_num| is int and might wrap around to a negative number when // casted from EnqueueOrder. This way of comparison handles that properly. return (sequence_num - other.sequence_num) <= 0; } return time < other.time; } }; } // namespace internal // PendingTask with extra metadata for SequenceManager. struct BASE_EXPORT Task : public PendingTask { Task(internal::PostedTask posted_task, TimeTicks delayed_run_time, EnqueueOrder sequence_order, EnqueueOrder enqueue_order = EnqueueOrder(), internal::WakeUpResolution wake_up_resolution = internal::WakeUpResolution::kLow); Task(Task&& move_from); ~Task(); Task& operator=(Task&& other); internal::DelayedWakeUp delayed_wake_up() const { return internal::DelayedWakeUp{delayed_run_time, sequence_num}; } // SequenceManager is particularly sensitive to enqueue order, // so we have accessors for safety. EnqueueOrder enqueue_order() const { DCHECK(enqueue_order_); return enqueue_order_; } void set_enqueue_order(EnqueueOrder enqueue_order) { DCHECK(!enqueue_order_); enqueue_order_ = enqueue_order; } bool enqueue_order_set() const { return enqueue_order_; } TaskType task_type; // The task runner this task is running on. Can be used by task runners that // support posting back to the "current sequence". scoped_refptr task_runner; #if DCHECK_IS_ON() bool cross_thread_; #endif private: // Similar to |sequence_num|, 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. This is because otherwise delayed tasks could run before // an immediate task posted after the delayed task. EnqueueOrder enqueue_order_; }; } // namespace sequence_manager } // namespace base #endif // BASE_TASK_SEQUENCE_MANAGER_TASKS_H_