Bug 1727960 - Use the start time of an idle task when nsRefreshDriver is ticking r=smaug,

Differential Revision: https://phabricator.services.mozilla.com/D123888
This commit is contained in:
Paul Bone 2021-09-02 01:17:28 +00:00
Родитель 3246980d94
Коммит 1d4aba58ac
2 изменённых файлов: 44 добавлений и 31 удалений

Просмотреть файл

@ -156,6 +156,23 @@ static void ScheduleTimedOut(nsITimer* aTimer, void* aClosure) {
runnable->Schedule(true);
}
void IdleTaskRunner::ScheduleAfterDelay(TimeDuration aDelay) {
if (!mScheduleTimer) {
mScheduleTimer = NS_NewTimer();
if (!mScheduleTimer) {
return;
}
} else {
mScheduleTimer->Cancel();
}
mScheduleTimer->InitWithNamedFuncCallback(
ScheduleTimedOut, this,
static_cast<unsigned long>(aDelay.ToMilliseconds()),
nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY, mName);
return;
}
void IdleTaskRunner::Schedule(bool aAllowIdleDispatch) {
if (!mCallback) {
return;
@ -169,6 +186,14 @@ void IdleTaskRunner::Schedule(bool aAllowIdleDispatch) {
mDeadline = TimeStamp();
TimeStamp now = TimeStamp::Now();
// This task isn't due to start yet
if (now < mStartTime) {
// + 1 to round milliseconds up to be sure to wait until after
// mStartTime.
ScheduleAfterDelay(mStartTime - now + TimeDuration::FromMilliseconds(1));
return;
}
if (nsRefreshDriver::IsRegularRateTimerTicking()) {
if (!mTask) {
// If a task was already scheduled, no point rescheduling.
@ -178,37 +203,23 @@ void IdleTaskRunner::Schedule(bool aAllowIdleDispatch) {
}
// Ensure we get called at some point, even if RefreshDriver is stopped.
SetTimerInternal(mMaxDelay);
} else {
if (aAllowIdleDispatch) {
SetTimerInternal(mMaxDelay);
if (!mTask) {
// If we have mTask we've already scheduled one, and the refresh driver
// shouldn't be running if we hit this code path.
mTask = new IdleTaskRunnerTask(this);
RefPtr<Task> task(mTask);
TaskController::Get()->AddTask(task.forget());
}
} else {
if (!mScheduleTimer) {
mScheduleTimer = NS_NewTimer();
if (!mScheduleTimer) {
return;
}
} else {
mScheduleTimer->Cancel();
}
// We weren't allowed to do idle dispatch immediately, do it after a
// short timeout. (Or wait for our start time if we haven't started yet.)
uint32_t waitToSchedule = 16; /* ms */
if (now < mStartTime) {
// + 1 to round milliseconds up to be sure to wait until after
// mStartTime.
waitToSchedule = (mStartTime - now).ToMilliseconds() + 1;
}
mScheduleTimer->InitWithNamedFuncCallback(
ScheduleTimedOut, this, waitToSchedule,
nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY, mName);
}
return;
}
// We aren't allowed to do idle dispatch now. So have it run after a short
// timeout.
if (!aAllowIdleDispatch) {
ScheduleAfterDelay(TimeDuration::FromMilliseconds(16));
return;
}
SetTimerInternal(mMaxDelay);
if (!mTask) {
// If we have mTask we've already scheduled one, and the refresh driver
// shouldn't be running if we hit this code path.
mTask = new IdleTaskRunnerTask(this);
RefPtr<Task> task(mTask);
TaskController::Get()->AddTask(task.forget());
}
}

Просмотреть файл

@ -82,6 +82,8 @@ class IdleTaskRunner {
void CancelTimer();
void SetTimerInternal(TimeDuration aDelay);
void ScheduleAfterDelay(TimeDuration aDelay);
nsCOMPtr<nsITimer> mTimer;
nsCOMPtr<nsITimer> mScheduleTimer;
CallbackType mCallback;