Merge autoland to mozilla-central. a=merge
[gecko.git] / xpcom / threads / IdlePeriodState.h
blob94d66156774c993438b40d2964d20275040857f2
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
10 /**
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"
21 #include "nsCOMPtr.h"
23 #include <stdint.h>
25 class nsIIdlePeriod;
27 namespace mozilla {
28 class TaskManager;
29 namespace ipc {
30 class IdleSchedulerChild;
31 } // namespace ipc
33 class IdlePeriodState {
34 public:
35 explicit IdlePeriodState(already_AddRefed<nsIIdlePeriod>&& aIdlePeriod);
37 ~IdlePeriodState();
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.
46 void FlagNotIdle();
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
77 // process.
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; }
104 protected:
105 void EnsureIsActive() {
106 if (!mActive) {
107 SetActive();
111 void EnsureIsPaused(const MutexAutoUnlock& aProofOfUnlock) {
112 if (mActive) {
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
128 // idle scheduler.
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
135 // this.
136 void ClearIdleToken();
138 // SetActive should be called when the event queue is running any type of
139 // tasks.
140 void SetActive();
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
149 // needed.
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.
191 bool mActive = true;
194 } // namespace mozilla
196 #endif // mozilla_IdlePeriodState_h