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"
15 class nsGlobalWindowInner
;
21 class TimeoutExecutor
;
24 // This class manages the timeouts in a Window's setTimeout/setInterval pool.
25 class TimeoutManager final
{
30 TimeoutManager(nsGlobalWindowInner
& aWindow
, uint32_t aMaxIdleDeferMS
);
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
,
47 void ClearTimeout(int32_t aTimerId
, mozilla::dom::Timeout::Reason aReason
);
48 bool ClearTimeoutInternal(int32_t aTimerId
,
49 mozilla::dom::Timeout::Reason aReason
,
52 // The timeout implementation functions.
54 void RunTimeout(const TimeStamp
& aNow
, const TimeStamp
& aTargetDeadline
,
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
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
);
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
);
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());
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
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
);
162 mTimeoutList
.clear();
165 template <class Callable
>
166 void ForEach(Callable c
) {
167 for (Timeout
* timeout
= GetFirst(); timeout
;
168 timeout
= timeout
->getNext()) {
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()) {
185 Timeout
* GetTimeout(uint32_t aTimeoutId
, Timeout::Reason aReason
) {
186 Timeout::TimeoutIdAndReason key
= {aTimeoutId
, aReason
};
187 return mTimeouts
->Get(key
);
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
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.
218 uint32_t mTimeoutIdCounter
;
219 uint32_t mNextFiringId
;
221 int64_t mFiringIndex
;
222 int64_t mLastFiringIndex
;
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
;
244 static uint32_t sNestingLevel
;
248 } // namespace mozilla