blob: 63168db8bd92ba6078d74f59a4ff7602994e274a [file] [log] [blame]
// Copyright 2018 The Chromium Authors
// 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 <optional>
#include "base/base_export.h"
#include "base/check.h"
#include "base/containers/intrusive_heap.h"
#include "base/dcheck_is_on.h"
#include "base/pending_task.h"
#include "base/task/delay_policy.h"
#include "base/task/sequence_manager/delayed_task_handle_delegate.h"
#include "base/task/sequence_manager/enqueue_order.h"
#include "base/task/sequenced_task_runner.h"
#include "third_party/abseil-cpp/absl/types/variant.h"
namespace base {
namespace sequence_manager {
using TaskType = uint8_t;
constexpr TaskType kTaskTypeNone = 0;
class TaskOrder;
namespace internal {
// 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<SequencedTaskRunner> task_runner,
OnceClosure callback,
Location location,
TimeDelta delay = base::TimeDelta(),
Nestable nestable = Nestable::kNestable,
TaskType task_type = kTaskTypeNone,
WeakPtr<DelayedTaskHandleDelegate>
delayed_task_handle_delegate = nullptr);
explicit PostedTask(scoped_refptr<SequencedTaskRunner> task_runner,
OnceClosure callback,
Location location,
TimeTicks delayed_run_time,
subtle::DelayPolicy delay_policy,
Nestable nestable = Nestable::kNestable,
TaskType task_type = kTaskTypeNone,
WeakPtr<DelayedTaskHandleDelegate>
delayed_task_handle_delegate = nullptr);
PostedTask(PostedTask&& move_from) noexcept;
PostedTask(const PostedTask&) = delete;
PostedTask& operator=(const PostedTask&) = delete;
~PostedTask();
bool is_delayed() const {
return absl::holds_alternative<TimeTicks>(delay_or_delayed_run_time)
? !absl::get<TimeTicks>(delay_or_delayed_run_time).is_null()
: !absl::get<TimeDelta>(delay_or_delayed_run_time).is_zero();
}
OnceClosure callback;
Location location;
Nestable nestable = Nestable::kNestable;
TaskType task_type = kTaskTypeNone;
absl::variant<TimeDelta, TimeTicks> delay_or_delayed_run_time;
subtle::DelayPolicy delay_policy = subtle::DelayPolicy::kFlexibleNoSooner;
// The task runner this task is running on. Can be used by task runners that
// support posting back to the "current sequence".
scoped_refptr<SequencedTaskRunner> task_runner;
// The delegate for the DelayedTaskHandle, if this task was posted through
// PostCancelableDelayedTask(), nullptr otherwise.
WeakPtr<DelayedTaskHandleDelegate> delayed_task_handle_delegate;
};
} // namespace internal
enum class WakeUpResolution { kLow, kHigh };
// Represents a time at which a task wants to run.
struct WakeUp {
// is_null() for immediate wake up.
TimeTicks time;
// These are meaningless if is_immediate().
TimeDelta leeway;
WakeUpResolution resolution = WakeUpResolution::kLow;
subtle::DelayPolicy delay_policy = subtle::DelayPolicy::kFlexibleNoSooner;
bool operator!=(const WakeUp& other) const {
return time != other.time || leeway != other.leeway ||
resolution != other.resolution || delay_policy != other.delay_policy;
}
bool operator==(const WakeUp& other) const { return !(*this != other); }
bool is_immediate() const { return time.is_null(); }
TimeTicks earliest_time() const;
TimeTicks latest_time() const;
};
// PendingTask with extra metadata for SequenceManager.
struct BASE_EXPORT Task : public PendingTask {
Task(internal::PostedTask posted_task,
EnqueueOrder sequence_order,
EnqueueOrder enqueue_order = EnqueueOrder(),
TimeTicks queue_time = TimeTicks(),
WakeUpResolution wake_up_resolution = WakeUpResolution::kLow,
TimeDelta leeway = TimeDelta());
Task(Task&& move_from);
~Task();
Task& operator=(Task&& other);
// 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_; }
TaskOrder task_order() const;
// OK to dispatch from a nested loop.
Nestable nestable = Nestable::kNonNestable;
// Needs high resolution timers.
bool is_high_res = false;
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<SequencedTaskRunner> task_runner;
#if DCHECK_IS_ON()
bool cross_thread_;
#endif
// Implement the intrusive heap contract.
void SetHeapHandle(HeapHandle heap_handle);
void ClearHeapHandle();
HeapHandle GetHeapHandle() const;
// Returns true if this task was canceled, either through weak pointer
// invalidation or through |delayed_task_handle_delegate_|.
bool IsCanceled() const;
// Must be invoked before running the task. Returns true if the task must run
// (any delayed task handle will have been invalidated by this method), false
// if it mustn't run (e.g. delayed task handle was invalidated prior to
// calling this method).
bool WillRunTask();
private:
// `enqueue_order_` is the primary component used to order tasks (see
// `TaskOrder`). 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_;
// The delegate for the DelayedTaskHandle, if this task was posted through
// `PostCancelableDelayedTask()`, not set otherwise. The task is canceled if
// `WeakPtr::WasInvalidated` is true. Note: if the task was not posted via
// `PostCancelableDelayedTask()`. the weak pointer won't be valid, but
// `WeakPtr::WasInvalidated` will be false.
WeakPtr<internal::DelayedTaskHandleDelegate> delayed_task_handle_delegate_;
};
} // namespace sequence_manager
} // namespace base
#endif // BASE_TASK_SEQUENCE_MANAGER_TASKS_H_