Bug 1850713: remove duplicated setting of early hint preloader id in `ScriptLoader...
[gecko.git] / dom / base / TimeoutManager.h
blobfd04a1b2155dca82f8c83d965ee806568569eb04
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
3 /* This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 #ifndef mozilla_dom_TimeoutManager_h__
8 #define mozilla_dom_TimeoutManager_h__
10 #include "mozilla/dom/Timeout.h"
11 #include "nsTArray.h"
13 class nsIEventTarget;
14 class nsITimer;
15 class nsGlobalWindowInner;
17 namespace mozilla {
19 namespace dom {
21 class TimeoutExecutor;
22 class TimeoutHandler;
24 // This class manages the timeouts in a Window's setTimeout/setInterval pool.
25 class TimeoutManager final {
26 private:
27 struct Timeouts;
29 public:
30 TimeoutManager(nsGlobalWindowInner& aWindow, uint32_t aMaxIdleDeferMS);
31 ~TimeoutManager();
32 TimeoutManager(const TimeoutManager& rhs) = delete;
33 void operator=(const TimeoutManager& rhs) = delete;
35 bool IsRunningTimeout() const;
37 static uint32_t GetNestingLevel() { return sNestingLevel; }
38 static void SetNestingLevel(uint32_t aLevel) { sNestingLevel = aLevel; }
40 bool HasTimeouts() const {
41 return !mTimeouts.IsEmpty() || !mIdleTimeouts.IsEmpty();
44 nsresult SetTimeout(TimeoutHandler* aHandler, int32_t interval,
45 bool aIsInterval, mozilla::dom::Timeout::Reason aReason,
46 int32_t* aReturn);
47 void ClearTimeout(int32_t aTimerId, mozilla::dom::Timeout::Reason aReason);
48 bool ClearTimeoutInternal(int32_t aTimerId,
49 mozilla::dom::Timeout::Reason aReason,
50 bool aIsIdle);
52 // The timeout implementation functions.
53 MOZ_CAN_RUN_SCRIPT
54 void RunTimeout(const TimeStamp& aNow, const TimeStamp& aTargetDeadline,
55 bool aProcessIdle);
57 void ClearAllTimeouts();
58 uint32_t GetTimeoutId(mozilla::dom::Timeout::Reason aReason);
60 TimeDuration CalculateDelay(Timeout* aTimeout) const;
62 // aTimeout is the timeout that we're about to start running. This function
63 // returns the current timeout.
64 mozilla::dom::Timeout* BeginRunningTimeout(mozilla::dom::Timeout* aTimeout);
65 // aTimeout is the last running timeout.
66 void EndRunningTimeout(mozilla::dom::Timeout* aTimeout);
68 void UnmarkGrayTimers();
70 // These four methods are intended to be called from the corresponding methods
71 // on nsGlobalWindow.
72 void Suspend();
73 void Resume();
74 void Freeze();
75 void Thaw();
77 // This should be called by nsGlobalWindow when the window might have moved
78 // to the background or foreground.
79 void UpdateBackgroundState();
81 // The document finished loading
82 void OnDocumentLoaded();
83 void StartThrottlingTimeouts();
85 // Run some code for each Timeout in our list. Note that this function
86 // doesn't guarantee that Timeouts are iterated in any particular order.
87 template <class Callable>
88 void ForEachUnorderedTimeout(Callable c) {
89 mIdleTimeouts.ForEach(c);
90 mTimeouts.ForEach(c);
93 void BeginSyncOperation();
94 void EndSyncOperation();
96 nsIEventTarget* EventTarget();
98 bool BudgetThrottlingEnabled(bool aIsBackground) const;
100 static const uint32_t InvalidFiringId;
102 void SetLoading(bool value);
104 private:
105 void MaybeStartThrottleTimeout();
107 // Return true if |aTimeout| needs to be reinserted into the timeout list.
108 bool RescheduleTimeout(mozilla::dom::Timeout* aTimeout,
109 const TimeStamp& aLastCallbackTime,
110 const TimeStamp& aCurrentNow);
112 void MoveIdleToActive();
114 bool IsBackground() const;
116 bool IsActive() const;
118 uint32_t CreateFiringId();
120 void DestroyFiringId(uint32_t aFiringId);
122 bool IsValidFiringId(uint32_t aFiringId) const;
124 bool IsInvalidFiringId(uint32_t aFiringId) const;
126 TimeDuration MinSchedulingDelay() const;
128 nsresult MaybeSchedule(const TimeStamp& aWhen,
129 const TimeStamp& aNow = TimeStamp::Now());
131 void RecordExecution(Timeout* aRunningTimeout, Timeout* aTimeout);
133 void UpdateBudget(const TimeStamp& aNow,
134 const TimeDuration& aDuration = TimeDuration());
136 private:
137 struct Timeouts {
138 explicit Timeouts(const TimeoutManager& aManager)
139 : mManager(aManager), mTimeouts(new Timeout::TimeoutSet()) {}
141 // Insert aTimeout into the list, before all timeouts that would
142 // fire after it, but no earlier than the last Timeout with a
143 // valid FiringId.
144 enum class SortBy { TimeRemaining, TimeWhen };
145 void Insert(mozilla::dom::Timeout* aTimeout, SortBy aSortBy);
147 const Timeout* GetFirst() const { return mTimeoutList.getFirst(); }
148 Timeout* GetFirst() { return mTimeoutList.getFirst(); }
149 const Timeout* GetLast() const { return mTimeoutList.getLast(); }
150 Timeout* GetLast() { return mTimeoutList.getLast(); }
151 bool IsEmpty() const { return mTimeoutList.isEmpty(); }
152 void InsertFront(Timeout* aTimeout) {
153 aTimeout->SetTimeoutContainer(mTimeouts);
154 mTimeoutList.insertFront(aTimeout);
156 void InsertBack(Timeout* aTimeout) {
157 aTimeout->SetTimeoutContainer(mTimeouts);
158 mTimeoutList.insertBack(aTimeout);
160 void Clear() {
161 mTimeouts->Clear();
162 mTimeoutList.clear();
165 template <class Callable>
166 void ForEach(Callable c) {
167 for (Timeout* timeout = GetFirst(); timeout;
168 timeout = timeout->getNext()) {
169 c(timeout);
173 // Returns true when a callback aborts iteration.
174 template <class Callable>
175 bool ForEachAbortable(Callable c) {
176 for (Timeout* timeout = GetFirst(); timeout;
177 timeout = timeout->getNext()) {
178 if (c(timeout)) {
179 return true;
182 return false;
185 Timeout* GetTimeout(uint32_t aTimeoutId, Timeout::Reason aReason) {
186 Timeout::TimeoutIdAndReason key = {aTimeoutId, aReason};
187 return mTimeouts->Get(key);
190 private:
191 // The TimeoutManager that owns this Timeouts structure. This is
192 // mainly used to call state inspecting methods like IsValidFiringId().
193 const TimeoutManager& mManager;
195 using TimeoutList = mozilla::LinkedList<RefPtr<Timeout>>;
197 // mTimeoutList is generally sorted by mWhen, but new values are always
198 // inserted after any Timeouts with a valid FiringId.
199 TimeoutList mTimeoutList;
201 // mTimeouts is a set of all the timeouts in the mTimeoutList.
202 // It let's one to have O(1) check whether a timeout id/reason is in the
203 // list.
204 RefPtr<Timeout::TimeoutSet> mTimeouts;
207 // Each nsGlobalWindowInner object has a TimeoutManager member. This
208 // reference points to that holder object.
209 nsGlobalWindowInner& mWindow;
210 // The executor is specific to the nsGlobalWindow/TimeoutManager, but it
211 // can live past the destruction of the window if its scheduled. Therefore
212 // it must be a separate ref-counted object.
213 RefPtr<TimeoutExecutor> mExecutor;
214 // For timeouts run off the idle queue
215 RefPtr<TimeoutExecutor> mIdleExecutor;
216 // The list of timeouts coming from non-tracking scripts.
217 Timeouts mTimeouts;
218 uint32_t mTimeoutIdCounter;
219 uint32_t mNextFiringId;
220 #ifdef DEBUG
221 int64_t mFiringIndex;
222 int64_t mLastFiringIndex;
223 #endif
224 AutoTArray<uint32_t, 2> mFiringIdStack;
225 mozilla::dom::Timeout* mRunningTimeout;
227 // Timeouts that would have fired but are being deferred until MainThread
228 // is idle (because we're loading)
229 Timeouts mIdleTimeouts;
231 // The current idle request callback timeout handle
232 uint32_t mIdleCallbackTimeoutCounter;
234 nsCOMPtr<nsITimer> mThrottleTimeoutsTimer;
235 mozilla::TimeStamp mLastBudgetUpdate;
236 mozilla::TimeDuration mExecutionBudget;
238 bool mThrottleTimeouts;
239 bool mThrottleTrackingTimeouts;
240 bool mBudgetThrottleTimeouts;
242 bool mIsLoading;
244 static uint32_t sNestingLevel;
247 } // namespace dom
248 } // namespace mozilla
250 #endif