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_IdlePeriodState_h
8 #define mozilla_IdlePeriodState_h
11 * A class for tracking the state of our idle period. This includes keeping
12 * track of both the state of our process-local idle period estimate and, for
13 * content processes, managing communication with the parent process for
14 * cross-pprocess idle detection.
17 #include "mozilla/MemoryReporting.h"
18 #include "mozilla/Mutex.h"
19 #include "mozilla/RefPtr.h"
20 #include "mozilla/TimeStamp.h"
30 class IdleSchedulerChild
;
33 class IdlePeriodState
{
35 explicit IdlePeriodState(already_AddRefed
<nsIIdlePeriod
>&& aIdlePeriod
);
39 // Integration with memory reporting.
40 size_t SizeOfExcludingThis(MallocSizeOf aMallocSizeOf
) const;
42 // Notification that whoever we are tracking idle state for has found a
43 // non-idle task to process.
45 // Must not be called while holding any locks.
48 // Notification that whoever we are tracking idle state for has no more
49 // tasks (idle or not) to process.
51 // aProofOfUnlock is the proof that our caller unlocked its mutex.
52 void RanOutOfTasks(const MutexAutoUnlock
& aProofOfUnlock
);
54 // Notification that whoever we are tracking idle state has idle tasks that
55 // they are considering ready to run and that we should keep claiming they are
56 // ready to run until they call ForgetPendingTaskGuarantee().
57 void EnforcePendingTaskGuarantee() {
58 mHasPendingEventsPromisedIdleEvent
= true;
61 // Notification that whoever we are tracking idle state for is done with our
62 // "we have an idle event ready to run" guarantee. When this happens, we can
63 // reset mHasPendingEventsPromisedIdleEvent to false, because we have
64 // fulfilled our contract.
65 void ForgetPendingTaskGuarantee() {
66 mHasPendingEventsPromisedIdleEvent
= false;
69 // Update our cached idle deadline so consumers can use it while holding
70 // locks. Consumers must ClearCachedIdleDeadline() once they are done.
71 void UpdateCachedIdleDeadline(const MutexAutoUnlock
& aProofOfUnlock
) {
72 mCachedIdleDeadline
= GetIdleDeadlineInternal(false, aProofOfUnlock
);
75 // If we have local idle deadline, but don't have an idle token, this will
76 // request such from the parent process when this is called in a child
78 void RequestIdleDeadlineIfNeeded(const MutexAutoUnlock
& aProofOfUnlock
) {
79 GetIdleDeadlineInternal(false, aProofOfUnlock
);
82 // Reset our cached idle deadline, so we stop allowing idle runnables to run.
83 void ClearCachedIdleDeadline() { mCachedIdleDeadline
= TimeStamp(); }
85 // Get the current cached idle deadline. This may return a null timestamp.
86 TimeStamp
GetCachedIdleDeadline() { return mCachedIdleDeadline
; }
88 // Peek our current idle deadline into mCachedIdleDeadline. This can cause
89 // mCachedIdleDeadline to be a null timestamp (which means we are not idle
90 // right now). This method does not have any side-effects on our state, apart
91 // from guaranteeing that if it returns non-null then GetDeadlineForIdleTask
92 // will return non-null until ForgetPendingTaskGuarantee() is called, and its
93 // effects on mCachedIdleDeadline.
95 // aProofOfUnlock is the proof that our caller unlocked its mutex.
96 void CachePeekedIdleDeadline(const MutexAutoUnlock
& aProofOfUnlock
) {
97 mCachedIdleDeadline
= GetIdleDeadlineInternal(true, aProofOfUnlock
);
100 void SetIdleToken(uint64_t aId
, TimeDuration aDuration
);
102 bool IsActive() { return mActive
; }
105 void EnsureIsActive() {
111 void EnsureIsPaused(const MutexAutoUnlock
& aProofOfUnlock
) {
113 SetPaused(aProofOfUnlock
);
117 // Returns a null TimeStamp if we're not in the idle period.
118 TimeStamp
GetLocalIdleDeadline(bool& aShuttingDown
,
119 const MutexAutoUnlock
& aProofOfUnlock
);
121 // Gets the idle token, which is the end time of the idle period.
123 // aProofOfUnlock is the proof that our caller unlocked its mutex.
124 TimeStamp
GetIdleToken(TimeStamp aLocalIdlePeriodHint
,
125 const MutexAutoUnlock
& aProofOfUnlock
);
127 // In case of child processes, requests idle time from the cross-process
129 void RequestIdleToken(TimeStamp aLocalIdlePeriodHint
);
131 // Mark that we don't have idle time to use, nor are expecting to get an idle
132 // token from the idle scheduler. This must be called while not holding any
133 // locks, but some of the callers aren't holding locks to start with, so
134 // consumers just need to make sure they are not holding locks when they call
136 void ClearIdleToken();
138 // SetActive should be called when the event queue is running any type of
141 // SetPaused should be called once the event queue doesn't have more
142 // tasks to process, or is waiting for the idle token.
144 // aProofOfUnlock is the proof that our caller unlocked its mutex.
145 void SetPaused(const MutexAutoUnlock
& aProofOfUnlock
);
147 // Get or peek our idle deadline. When peeking, we generally don't change any
148 // of our internal state. When getting, we may request an idle token as
151 // aProofOfUnlock is the proof that our caller unlocked its mutex.
152 TimeStamp
GetIdleDeadlineInternal(bool aIsPeek
,
153 const MutexAutoUnlock
& aProofOfUnlock
);
155 // Whether we should be getting an idle token (i.e. are a content process
156 // and are using cross process idle scheduling).
157 bool ShouldGetIdleToken();
159 // Set to true if we have claimed we have a ready-to-run idle task when asked.
160 // In that case, we will ensure that we allow at least one task to run when
161 // someone tries to run a task, even if we have run out of idle period at that
162 // point. This ensures that we never fail to produce a task to run if we
163 // claim we have a task ready to run.
164 bool mHasPendingEventsPromisedIdleEvent
= false;
166 // mIdlePeriod keeps track of the current idle period. Calling
167 // mIdlePeriod->GetIdlePeriodHint() will give an estimate of when
168 // the current idle period will end.
169 nsCOMPtr
<nsIIdlePeriod
> mIdlePeriod
;
171 // If non-null, this timestamp represents the end time of the idle period. An
172 // idle period starts when we get the idle token from the parent process and
173 // ends when either there are no more things we want to run at idle priority
174 // or mIdleToken < TimeStamp::Now(), so we have reached our idle deadline.
175 TimeStamp mIdleToken
;
177 // The id of the last idle request to the cross-process idle scheduler.
178 uint64_t mIdleRequestId
= 0;
180 // If we're in a content process, we use mIdleScheduler to communicate with
181 // the parent process for purposes of cross-process idle tracking.
182 RefPtr
<mozilla::ipc::IdleSchedulerChild
> mIdleScheduler
;
184 // Our cached idle deadline. This is set by UpdateCachedIdleDeadline() and
185 // cleared by ClearCachedIdleDeadline(). Consumers should do the former while
186 // not holding any locks, but may do the latter while holding locks.
187 TimeStamp mCachedIdleDeadline
;
189 // mActive is true when the PrioritizedEventQueue or TaskController we are
190 // associated with is running tasks.
194 } // namespace mozilla
196 #endif // mozilla_IdlePeriodState_h