1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153
|
// Copyright 2021 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_WAKE_UP_QUEUE_H_
#define BASE_TASK_SEQUENCE_MANAGER_WAKE_UP_QUEUE_H_
#include <optional>
#include "base/base_export.h"
#include "base/check.h"
#include "base/containers/intrusive_heap.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/raw_ptr_exclusion.h"
#include "base/task/common/lazy_now.h"
#include "base/task/sequence_manager/task_queue_impl.h"
#include "base/time/time.h"
#include "base/values.h"
namespace base {
namespace sequence_manager {
class EnqueueOrder;
namespace internal {
class AssociatedThreadId;
class SequenceManagerImpl;
class TaskQueueImpl;
// WakeUpQueue is a queue of (wake_up, TaskQueueImpl*) pairs which
// aggregates wake-ups from multiple TaskQueueImpl into a single wake-up, and
// notifies TaskQueueImpls when wake-up times are reached.
class BASE_EXPORT WakeUpQueue {
public:
WakeUpQueue(const WakeUpQueue&) = delete;
WakeUpQueue& operator=(const WakeUpQueue&) = delete;
virtual ~WakeUpQueue();
// Returns a wake-up for the next pending delayed task (pending delayed tasks
// that are ripe may be ignored). If there are no such tasks (immediate tasks
// don't count) or queues are disabled it returns nullopt.
std::optional<WakeUp> GetNextDelayedWakeUp() const;
// Debug info.
Value::Dict AsValue(TimeTicks now) const;
// Returns true if there are no pending delayed tasks.
bool empty() const { return wake_up_queue_.empty(); }
// Moves ready delayed tasks in TaskQueues to delayed WorkQueues, consuming
// expired wake-ups in the process.
void MoveReadyDelayedTasksToWorkQueues(LazyNow* lazy_now,
EnqueueOrder enqueue_order);
// Schedule `queue` to wake up at certain time. Repeating calls with the same
// `queue` invalidate previous requests. Nullopt `wake_up` cancels a
// previously set wake up for `queue`.
void SetNextWakeUpForQueue(internal::TaskQueueImpl* queue,
LazyNow* lazy_now,
std::optional<WakeUp> wake_up);
// Remove the TaskQueue from any internal data structures.
virtual void UnregisterQueue(internal::TaskQueueImpl* queue) = 0;
// Removes all canceled delayed tasks from the front of the queue. After
// calling this, GetNextDelayedWakeUp() is guaranteed to return a wake up time
// for a non-canceled task.
void RemoveAllCanceledDelayedTasksFromFront(LazyNow* lazy_now);
protected:
explicit WakeUpQueue(
scoped_refptr<const internal::AssociatedThreadId> associated_thread);
// Called every time the next `next_wake_up` changes. std::nullopt is used to
// cancel the next wake-up. Subclasses may use this to tell SequenceManager to
// schedule the next wake-up at the given time.
virtual void OnNextWakeUpChanged(LazyNow* lazy_now,
std::optional<WakeUp> next_wake_up) = 0;
virtual const char* GetName() const = 0;
private:
friend class MockWakeUpQueue;
struct ScheduledWakeUp {
WakeUp wake_up;
// RAW_PTR_EXCLUSION: Performance reasons (based on analysis of
// speedometer3).
RAW_PTR_EXCLUSION internal::TaskQueueImpl* queue = nullptr;
bool operator>(const ScheduledWakeUp& other) const {
return wake_up.latest_time() > other.wake_up.latest_time();
}
void SetHeapHandle(HeapHandle handle) {
DCHECK(handle.IsValid());
queue->set_heap_handle(handle);
}
void ClearHeapHandle() {
DCHECK(queue->heap_handle().IsValid());
queue->set_heap_handle(HeapHandle());
}
HeapHandle GetHeapHandle() const { return queue->heap_handle(); }
};
IntrusiveHeap<ScheduledWakeUp, std::greater<>> wake_up_queue_;
const scoped_refptr<const internal::AssociatedThreadId> associated_thread_;
};
// Default WakeUpQueue implementation that forwards wake-ups to
// `sequence_manager_`.
class BASE_EXPORT DefaultWakeUpQueue : public WakeUpQueue {
public:
DefaultWakeUpQueue(
scoped_refptr<internal::AssociatedThreadId> associated_thread,
internal::SequenceManagerImpl* sequence_manager);
~DefaultWakeUpQueue() override;
private:
// WakeUpQueue implementation:
void OnNextWakeUpChanged(LazyNow* lazy_now,
std::optional<WakeUp> wake_up) override;
const char* GetName() const override;
void UnregisterQueue(internal::TaskQueueImpl* queue) override;
raw_ptr<internal::SequenceManagerImpl> sequence_manager_; // Not owned.
};
// WakeUpQueue implementation that doesn't sends wake-ups to
// any SequenceManager, such that task queues don't cause wake-ups.
class BASE_EXPORT NonWakingWakeUpQueue : public WakeUpQueue {
public:
explicit NonWakingWakeUpQueue(
scoped_refptr<internal::AssociatedThreadId> associated_thread);
~NonWakingWakeUpQueue() override;
private:
// WakeUpQueue implementation:
void OnNextWakeUpChanged(LazyNow* lazy_now,
std::optional<WakeUp> wake_up) override;
const char* GetName() const override;
void UnregisterQueue(internal::TaskQueueImpl* queue) override;
};
} // namespace internal
} // namespace sequence_manager
} // namespace base
#endif // BASE_TASK_SEQUENCE_MANAGER_WAKE_UP_QUEUE_H_
|