зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1355746 - Part 1. Rename CollectRunner to IdleTaskRunner and move to xpcom/threads/IdleTaskRunner.h/cpp r=smaug
Nothing is changed in this patch except for renaming and code move around. The strategy is to have the final file setup in this patch without any detail change. The actual code change will be in the next patch so that we can focus on reviewing the diff in the next patch regarding IdleTaskRunner. MozReview-Commit-ID: 4Bul9mZ7z1n --HG-- extra : rebase_source : 21d7d601c70304d69100d96cecfdb3e0322cb777 extra : intermediate-source : 366862231c26e085fe749012a09418aa31936224 extra : source : 7b4e77911d1471c33fda0a43b50ed17c5274e795
This commit is contained in:
Родитель
1d88de7d2f
Коммит
e13aeee5fd
|
@ -87,6 +87,7 @@
|
|||
|
||||
#include "nsCycleCollectionNoteRootCallback.h"
|
||||
#include "GeckoProfiler.h"
|
||||
#include "mozilla/IdleTaskRunner.h"
|
||||
|
||||
using namespace mozilla;
|
||||
using namespace mozilla::dom;
|
||||
|
@ -120,7 +121,7 @@ const size_t gStackSize = 8192;
|
|||
#define NS_CC_SKIPPABLE_DELAY 250 // ms
|
||||
|
||||
// ForgetSkippable is usually fast, so we can use small budgets.
|
||||
// This isn't a real budget but a hint to CollectorRunner whether there
|
||||
// This isn't a real budget but a hint to IdleTaskRunner whether there
|
||||
// is enough time to call ForgetSkippable.
|
||||
static const int64_t kForgetSkippableSliceDuration = 2;
|
||||
|
||||
|
@ -149,16 +150,14 @@ static const uint32_t kMaxICCDuration = 2000; // ms
|
|||
// Large value used to specify that a script should run essentially forever
|
||||
#define NS_UNLIMITED_SCRIPT_RUNTIME (0x40000000LL << 32)
|
||||
|
||||
class CollectorRunner;
|
||||
|
||||
// if you add statics here, add them to the list in StartupJSEnvironment
|
||||
|
||||
static nsITimer *sGCTimer;
|
||||
static nsITimer *sShrinkingGCTimer;
|
||||
static StaticRefPtr<CollectorRunner> sCCRunner;
|
||||
static StaticRefPtr<CollectorRunner> sICCRunner;
|
||||
static StaticRefPtr<IdleTaskRunner> sCCRunner;
|
||||
static StaticRefPtr<IdleTaskRunner> sICCRunner;
|
||||
static nsITimer *sFullGCTimer;
|
||||
static StaticRefPtr<CollectorRunner> sInterSliceGCRunner;
|
||||
static StaticRefPtr<IdleTaskRunner> sInterSliceGCRunner;
|
||||
|
||||
static TimeStamp sLastCCEndTime;
|
||||
|
||||
|
@ -228,183 +227,6 @@ static int32_t sExpensiveCollectorPokes = 0;
|
|||
static const int32_t kPokesBetweenExpensiveCollectorTriggers = 5;
|
||||
|
||||
static TimeDuration sGCUnnotifiedTotalTime;
|
||||
|
||||
// Return true if some meaningful work was done.
|
||||
typedef bool (*CollectorRunnerCallback) (TimeStamp aDeadline, void* aData);
|
||||
|
||||
// Repeating callback runner for CC and GC.
|
||||
class CollectorRunner final : public IdleRunnable
|
||||
{
|
||||
public:
|
||||
static already_AddRefed<CollectorRunner>
|
||||
Create(CollectorRunnerCallback aCallback, uint32_t aDelay,
|
||||
int64_t aBudget, bool aRepeating, void* aData = nullptr)
|
||||
{
|
||||
if (sShuttingDown) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<CollectorRunner> runner =
|
||||
new CollectorRunner(aCallback, aDelay, aBudget, aRepeating, aData);
|
||||
runner->Schedule(false); // Initial scheduling shouldn't use idle dispatch.
|
||||
return runner.forget();
|
||||
}
|
||||
|
||||
NS_IMETHOD Run() override
|
||||
{
|
||||
if (!mCallback) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Deadline is null when called from timer.
|
||||
bool deadLineWasNull = mDeadline.IsNull();
|
||||
bool didRun = false;
|
||||
if (deadLineWasNull || ((TimeStamp::Now() + mBudget) < mDeadline)) {
|
||||
CancelTimer();
|
||||
didRun = mCallback(mDeadline, mData);
|
||||
}
|
||||
|
||||
if (mCallback && (mRepeating || !didRun)) {
|
||||
// If we didn't do meaningful work, don't schedule using immediate
|
||||
// idle dispatch, since that could lead to a loop until the idle
|
||||
// period ends.
|
||||
Schedule(didRun);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
TimedOut(nsITimer* aTimer, void* aClosure)
|
||||
{
|
||||
RefPtr<CollectorRunner> runnable = static_cast<CollectorRunner*>(aClosure);
|
||||
runnable->Run();
|
||||
}
|
||||
|
||||
void SetDeadline(mozilla::TimeStamp aDeadline) override
|
||||
{
|
||||
mDeadline = aDeadline;
|
||||
};
|
||||
|
||||
void SetTimer(uint32_t aDelay, nsIEventTarget* aTarget) override
|
||||
{
|
||||
if (mTimerActive) {
|
||||
return;
|
||||
}
|
||||
|
||||
mTarget = aTarget;
|
||||
if (!mTimer) {
|
||||
mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
|
||||
} else {
|
||||
mTimer->Cancel();
|
||||
}
|
||||
|
||||
if (mTimer) {
|
||||
mTimer->SetTarget(mTarget);
|
||||
mTimer->InitWithFuncCallback(TimedOut, this, aDelay,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
mTimerActive = true;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult Cancel() override
|
||||
{
|
||||
CancelTimer();
|
||||
mTimer = nullptr;
|
||||
mScheduleTimer = nullptr;
|
||||
mCallback = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
ScheduleTimedOut(nsITimer* aTimer, void* aClosure)
|
||||
{
|
||||
RefPtr<CollectorRunner> runnable = static_cast<CollectorRunner*>(aClosure);
|
||||
runnable->Schedule(true);
|
||||
}
|
||||
|
||||
void Schedule(bool aAllowIdleDispatch)
|
||||
{
|
||||
if (!mCallback) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sShuttingDown) {
|
||||
Cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
mDeadline = TimeStamp();
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
TimeStamp hint = nsRefreshDriver::GetIdleDeadlineHint(now);
|
||||
if (hint != now) {
|
||||
// RefreshDriver is ticking, let it schedule the idle dispatch.
|
||||
nsRefreshDriver::DispatchIdleRunnableAfterTick(this, mDelay);
|
||||
// Ensure we get called at some point, even if RefreshDriver is stopped.
|
||||
SetTimer(mDelay, mTarget);
|
||||
} else {
|
||||
// RefreshDriver doesn't seem to be running.
|
||||
if (aAllowIdleDispatch) {
|
||||
nsCOMPtr<nsIRunnable> runnable = this;
|
||||
NS_IdleDispatchToCurrentThread(runnable.forget(), mDelay);
|
||||
SetTimer(mDelay, mTarget);
|
||||
} else {
|
||||
if (!mScheduleTimer) {
|
||||
mScheduleTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
|
||||
if (!mScheduleTimer) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
mScheduleTimer->Cancel();
|
||||
}
|
||||
|
||||
// We weren't allowed to do idle dispatch immediately, do it after a
|
||||
// short timeout.
|
||||
mScheduleTimer->InitWithFuncCallback(ScheduleTimedOut, this, 16,
|
||||
nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
explicit CollectorRunner(CollectorRunnerCallback aCallback,
|
||||
uint32_t aDelay, int64_t aBudget,
|
||||
bool aRepeating, void* aData)
|
||||
: mCallback(aCallback), mDelay(aDelay)
|
||||
, mBudget(TimeDuration::FromMilliseconds(aBudget))
|
||||
, mRepeating(aRepeating), mTimerActive(false), mData(aData)
|
||||
{
|
||||
}
|
||||
|
||||
~CollectorRunner()
|
||||
{
|
||||
CancelTimer();
|
||||
}
|
||||
|
||||
void CancelTimer()
|
||||
{
|
||||
nsRefreshDriver::CancelIdleRunnable(this);
|
||||
if (mTimer) {
|
||||
mTimer->Cancel();
|
||||
}
|
||||
if (mScheduleTimer) {
|
||||
mScheduleTimer->Cancel();
|
||||
}
|
||||
mTimerActive = false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
nsCOMPtr<nsITimer> mScheduleTimer;
|
||||
nsCOMPtr<nsIEventTarget> mTarget;
|
||||
CollectorRunnerCallback mCallback;
|
||||
uint32_t mDelay;
|
||||
TimeStamp mDeadline;
|
||||
TimeDuration mBudget;
|
||||
bool mRepeating;
|
||||
bool mTimerActive;
|
||||
void* mData;
|
||||
};
|
||||
|
||||
static const char*
|
||||
ProcessNameForCollectorLog()
|
||||
{
|
||||
|
|
|
@ -0,0 +1,172 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "IdleTaskRunner.h"
|
||||
#include "nsRefreshDriver.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
already_AddRefed<IdleTaskRunner>
|
||||
IdleTaskRunner::Create(IdleTaskRunnerCallback aCallback, uint32_t aDelay,
|
||||
int64_t aBudget, bool aRepeating, void* aData)
|
||||
{
|
||||
if (sShuttingDown) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<IdleTaskRunner> runner =
|
||||
new IdleTaskRunner(aCallback, aDelay, aBudget, aRepeating, aData);
|
||||
runner->Schedule(false); // Initial scheduling shouldn't use idle dispatch.
|
||||
return runner.forget();
|
||||
}
|
||||
|
||||
IdleTaskRunner::IdleTaskRunner(IdleTaskRunnerCallback aCallback,
|
||||
uint32_t aDelay, int64_t aBudget,
|
||||
bool aRepeating, void* aData)
|
||||
: mCallback(aCallback), mDelay(aDelay)
|
||||
, mBudget(TimeDuration::FromMilliseconds(aBudget))
|
||||
, mRepeating(aRepeating), mTimerActive(false), mData(aData)
|
||||
{
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
IdleTaskRunner::Run()
|
||||
{
|
||||
if (!mCallback) {
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Deadline is null when called from timer.
|
||||
bool deadLineWasNull = mDeadline.IsNull();
|
||||
bool didRun = false;
|
||||
if (deadLineWasNull || ((TimeStamp::Now() + mBudget) < mDeadline)) {
|
||||
CancelTimer();
|
||||
didRun = mCallback(mDeadline, mData);
|
||||
}
|
||||
|
||||
if (mCallback && (mRepeating || !didRun)) {
|
||||
// If we didn't do meaningful work, don't schedule using immediate
|
||||
// idle dispatch, since that could lead to a loop until the idle
|
||||
// period ends.
|
||||
Schedule(didRun);
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
TimedOut(nsITimer* aTimer, void* aClosure)
|
||||
{
|
||||
RefPtr<IdleTaskRunner> runnable = static_cast<IdleTaskRunner*>(aClosure);
|
||||
runnable->Run();
|
||||
}
|
||||
|
||||
void
|
||||
IdleTaskRunner::SetDeadline(mozilla::TimeStamp aDeadline)
|
||||
{
|
||||
mDeadline = aDeadline;
|
||||
};
|
||||
|
||||
void IdleTaskRunner::SetTimer(uint32_t aDelay, nsIEventTarget* aTarget)
|
||||
{
|
||||
if (mTimerActive) {
|
||||
return;
|
||||
}
|
||||
mTarget = aTarget;
|
||||
if (!mTimer) {
|
||||
mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
|
||||
} else {
|
||||
mTimer->Cancel();
|
||||
}
|
||||
|
||||
if (mTimer) {
|
||||
mTimer->SetTarget(mTarget);
|
||||
mTimer->InitWithFuncCallback(TimedOut, this, aDelay,
|
||||
nsITimer::TYPE_ONE_SHOT);
|
||||
mTimerActive = true;
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
IdleTaskRunner::Cancel()
|
||||
{
|
||||
CancelTimer();
|
||||
mTimer = nullptr;
|
||||
mScheduleTimer = nullptr;
|
||||
mCallback = nullptr;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
ScheduleTimedOut(nsITimer* aTimer, void* aClosure)
|
||||
{
|
||||
RefPtr<IdleTaskRunner> runnable = static_cast<IdleTaskRunner*>(aClosure);
|
||||
runnable->Schedule(true);
|
||||
}
|
||||
|
||||
void
|
||||
IdleTaskRunner::Schedule(bool aAllowIdleDispatch)
|
||||
{
|
||||
if (!mCallback) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (sShuttingDown) {
|
||||
Cancel();
|
||||
return;
|
||||
}
|
||||
|
||||
mDeadline = TimeStamp();
|
||||
TimeStamp now = TimeStamp::Now();
|
||||
TimeStamp hint = nsRefreshDriver::GetIdleDeadlineHint(now);
|
||||
if (hint != now) {
|
||||
// RefreshDriver is ticking, let it schedule the idle dispatch.
|
||||
nsRefreshDriver::DispatchIdleRunnableAfterTick(this, mDelay);
|
||||
// Ensure we get called at some point, even if RefreshDriver is stopped.
|
||||
SetTimer(mDelay, mTarget);
|
||||
} else {
|
||||
// RefreshDriver doesn't seem to be running.
|
||||
if (aAllowIdleDispatch) {
|
||||
nsCOMPtr<nsIRunnable> runnable = this;
|
||||
NS_IdleDispatchToCurrentThread(runnable.forget(), mDelay);
|
||||
SetTimer(mDelay, mTarget);
|
||||
} else {
|
||||
if (!mScheduleTimer) {
|
||||
mScheduleTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
|
||||
if (!mScheduleTimer) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
mScheduleTimer->Cancel();
|
||||
}
|
||||
|
||||
// We weren't allowed to do idle dispatch immediately, do it after a
|
||||
// short timeout.
|
||||
mScheduleTimer->InitWithFuncCallback(ScheduleTimedOut, this, 16,
|
||||
nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IdleTaskRunner::~IdleTaskRunner()
|
||||
{
|
||||
CancelTimer();
|
||||
}
|
||||
|
||||
void
|
||||
IdleTaskRunner::CancelTimer()
|
||||
{
|
||||
nsRefreshDriver::CancelIdleRunnable(this);
|
||||
if (mTimer) {
|
||||
mTimer->Cancel();
|
||||
}
|
||||
if (mScheduleTimer) {
|
||||
mScheduleTimer->Cancel();
|
||||
}
|
||||
mTimerActive = false;
|
||||
}
|
||||
|
||||
} // end of namespace mozilla
|
|
@ -0,0 +1,54 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef IdleTaskRunner_h
|
||||
#define IdleTaskRunner_h
|
||||
|
||||
#include "nsThreadUtils.h"
|
||||
|
||||
namespace mozilla {
|
||||
|
||||
// Return true if some meaningful work was done.
|
||||
typedef bool (*IdleTaskRunnerCallback) (TimeStamp aDeadline, void* aData);
|
||||
|
||||
// Repeating callback runner for CC and GC.
|
||||
class IdleTaskRunner final : public IdleRunnable
|
||||
{
|
||||
public:
|
||||
static already_AddRefed<IdleTaskRunner>
|
||||
Create(IdleTaskRunnerCallback aCallback, uint32_t aDelay,
|
||||
int64_t aBudget, bool aRepeating, void* aData = nullptr);
|
||||
|
||||
NS_IMETHOD Run() override;
|
||||
|
||||
void SetDeadline(mozilla::TimeStamp aDeadline) override;
|
||||
void SetTimer(uint32_t aDelay, nsIEventTarget* aTarget) override;
|
||||
|
||||
nsresult Cancel() override;
|
||||
void Schedule(bool aAllowIdleDispatch);
|
||||
|
||||
private:
|
||||
explicit IdleTaskRunner(IdleTaskRunnerCallback aCallback,
|
||||
uint32_t aDelay, int64_t aBudget,
|
||||
bool aRepeating, void* aData);
|
||||
~IdleTaskRunner();
|
||||
void CancelTimer();
|
||||
|
||||
nsCOMPtr<nsITimer> mTimer;
|
||||
nsCOMPtr<nsITimer> mScheduleTimer;
|
||||
nsCOMPtr<nsIEventTarget> mTarget;
|
||||
IdleTaskRunnerCallback mCallback;
|
||||
uint32_t mDelay;
|
||||
TimeStamp mDeadline;
|
||||
TimeDuration mBudget;
|
||||
bool mRepeating;
|
||||
bool mTimerActive;
|
||||
void* mData;
|
||||
};
|
||||
|
||||
} // end of unnamed namespace.
|
||||
|
||||
#endif
|
|
@ -42,6 +42,7 @@ EXPORTS.mozilla += [
|
|||
'DeadlockDetector.h',
|
||||
'HangAnnotations.h',
|
||||
'HangMonitor.h',
|
||||
'IdleTaskRunner.h',
|
||||
'LazyIdleThread.h',
|
||||
'MainThreadIdlePeriod.h',
|
||||
'Monitor.h',
|
||||
|
@ -67,6 +68,7 @@ UNIFIED_SOURCES += [
|
|||
'BlockingResourceBase.cpp',
|
||||
'HangAnnotations.cpp',
|
||||
'HangMonitor.cpp',
|
||||
'IdleTaskRunner.cpp',
|
||||
'LazyIdleThread.cpp',
|
||||
'MainThreadIdlePeriod.cpp',
|
||||
'nsEnvironment.cpp',
|
||||
|
|
Загрузка…
Ссылка в новой задаче