File: wake_up_queue.h

package info (click to toggle)
chromium 139.0.7258.127-1
  • links: PTS, VCS
  • area: main
  • in suites:
  • size: 6,122,068 kB
  • sloc: cpp: 35,100,771; ansic: 7,163,530; javascript: 4,103,002; python: 1,436,920; asm: 946,517; xml: 746,709; pascal: 187,653; perl: 88,691; sh: 88,436; objc: 79,953; sql: 51,488; cs: 44,583; fortran: 24,137; makefile: 22,147; tcl: 15,277; php: 13,980; yacc: 8,984; ruby: 7,485; awk: 3,720; lisp: 3,096; lex: 1,327; ada: 727; jsp: 228; sed: 36
file content (153 lines) | stat: -rw-r--r-- 5,341 bytes parent folder | download | duplicates (5)
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_