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 : 22aeb5dca58501ec335ef8bc7b0efb6aea565bbf
This commit is contained in:
Henry Chang 2017-07-12 09:18:57 +08:00
Родитель 397425a083
Коммит f991045c00
4 изменённых файлов: 233 добавлений и 184 удалений

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

@ -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;
@ -229,184 +228,6 @@ 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->InitWithNamedFuncCallback(TimedOut, this, aDelay,
nsITimer::TYPE_ONE_SHOT,
"CollectorRunner");
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->InitWithNamedFuncCallback(ScheduleTimedOut, this, 16,
nsITimer::TYPE_ONE_SHOT_LOW_PRIORITY,
"CollectorRunner");
}
}
}
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->InitWithNamedFuncCallback(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->InitWithNamedFuncCallback(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',