180 lines
6.5 KiB
C++
180 lines
6.5 KiB
C++
// 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 "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/optional.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_
|