Bug 814771 - Add a cancelable runnable and use it to cancel a pending memory minimization procedure when an application is brought to the foreground r=jlebar

This commit is contained in:
Gabriele Svelto 2012-12-11 19:13:29 +01:00
parent 89f18cd5ea
commit c95ca6c01f
9 changed files with 116 additions and 9 deletions

View File

@ -113,6 +113,7 @@ private:
nsTArray<nsWeakPtr> mWindows;
nsCOMPtr<nsITimer> mGracePeriodTimer;
nsWeakPtr mMemoryMinimizerRunnable;
TimeStamp mStartupTime;
};
@ -283,6 +284,13 @@ ProcessPriorityManager::SetPriority(ProcessPriority aPriority)
mGracePeriodTimer = nullptr;
}
// Cancel the memory minimization procedure we might have started.
nsCOMPtr<nsICancelableRunnable> runnable =
do_QueryReferent(mMemoryMinimizerRunnable);
if (runnable) {
runnable->Cancel();
}
LOG("Setting priority to %d.", aPriority);
mProcessPriority = aPriority;
hal::SetProcessPriority(getpid(), aPriority);
@ -310,7 +318,17 @@ ProcessPriorityManager::OnGracePeriodTimerFired()
nsCOMPtr<nsIMemoryReporterManager> mgr =
do_GetService("@mozilla.org/memory-reporter-manager;1");
if (mgr) {
mgr->MinimizeMemoryUsage(/* callback = */ nullptr);
nsCOMPtr<nsICancelableRunnable> runnable =
do_QueryReferent(mMemoryMinimizerRunnable);
// Cancel the previous task if it's still pending
if (runnable) {
runnable->Cancel();
}
mgr->MinimizeMemoryUsage(/* callback = */ nullptr,
getter_AddRefs(runnable));
mMemoryMinimizerRunnable = do_GetWeakReference(runnable);
}
}

View File

@ -7,6 +7,7 @@
interface nsISimpleEnumerator;
interface nsIRunnable;
interface nsICancelableRunnable;
/*
* Memory reporters measure Firefox's memory usage. They are mainly used to
@ -226,7 +227,7 @@ interface nsIMemoryMultiReporter : nsISupports
readonly attribute int64_t explicitNonHeap;
};
[scriptable, builtinclass, uuid(8b670411-ea2a-44c2-a36b-529db0670821)]
[scriptable, builtinclass, uuid(0baaa958-3112-4952-b557-2a0c57eabb8f)]
interface nsIMemoryReporterManager : nsISupports
{
/*
@ -296,9 +297,9 @@ interface nsIMemoryReporterManager : nsISupports
/*
* Run a series of GC/CC's in an attempt to minimize the application's memory
* usage. When we're finished, we invoke the given runnable if it's not
* null.
* null. Returns a reference to the runnable used for carrying out the task.
*/
void minimizeMemoryUsage(in nsIRunnable callback);
nsICancelableRunnable minimizeMemoryUsage(in nsIRunnable callback);
};
%{C++

View File

@ -336,7 +336,8 @@ nsMemoryInfoDumper::DumpMemoryReportsToFile(
nsCOMPtr<nsIMemoryReporterManager> mgr =
do_GetService("@mozilla.org/memory-reporter-manager;1");
NS_ENSURE_TRUE(mgr, NS_ERROR_FAILURE);
mgr->MinimizeMemoryUsage(callback);
nsCOMPtr<nsICancelableRunnable> runnable;
mgr->MinimizeMemoryUsage(callback, getter_AddRefs(runnable));
return NS_OK;
}

View File

@ -949,16 +949,21 @@ namespace {
* When this sequence finishes, we invoke the callback function passed to the
* runnable's constructor.
*/
class MinimizeMemoryUsageRunnable : public nsRunnable
class MinimizeMemoryUsageRunnable : public nsCancelableRunnable
{
public:
MinimizeMemoryUsageRunnable(nsIRunnable* aCallback)
: mCallback(aCallback)
, mRemainingIters(sNumIters)
, mCanceled(false)
{}
NS_IMETHOD Run()
{
if (mCanceled) {
return NS_OK;
}
nsCOMPtr<nsIObserverService> os = services::GetObserverService();
if (!os) {
return NS_ERROR_FAILURE;
@ -981,6 +986,17 @@ public:
return NS_OK;
}
NS_IMETHOD Cancel()
{
if (mCanceled) {
return NS_ERROR_UNEXPECTED;
}
mCanceled = true;
return NS_OK;
}
private:
// Send sNumIters heap-minimize notifications, spinning the event
// loop after each notification (see bug 610166 comment 12 for an
@ -989,15 +1005,21 @@ private:
nsCOMPtr<nsIRunnable> mCallback;
uint32_t mRemainingIters;
bool mCanceled;
};
} // anonymous namespace
NS_IMETHODIMP
nsMemoryReporterManager::MinimizeMemoryUsage(nsIRunnable* aCallback)
nsMemoryReporterManager::MinimizeMemoryUsage(nsIRunnable* aCallback,
nsICancelableRunnable **result)
{
nsRefPtr<MinimizeMemoryUsageRunnable> runnable =
NS_ENSURE_ARG_POINTER(result);
nsRefPtr<nsICancelableRunnable> runnable =
new MinimizeMemoryUsageRunnable(aCallback);
NS_ADDREF(*result = runnable);
return NS_DispatchToMainThread(runnable);
}

View File

@ -29,7 +29,7 @@
#ifndef XPCOM_GLUE_AVOID_NSPR
NS_IMPL_THREADSAFE_ISUPPORTS1(nsRunnable, nsIRunnable)
NS_IMETHODIMP
nsRunnable::Run()
{
@ -37,6 +37,22 @@ nsRunnable::Run()
return NS_OK;
}
NS_IMPL_THREADSAFE_ISUPPORTS1(nsCancelableRunnable, nsICancelableRunnable)
NS_IMETHODIMP
nsCancelableRunnable::Run()
{
// Do nothing
return NS_OK;
}
NS_IMETHODIMP
nsCancelableRunnable::Cancel()
{
// Do nothing
return NS_OK;
}
#endif // XPCOM_GLUE_AVOID_NSPR
//-----------------------------------------------------------------------------

View File

@ -12,6 +12,7 @@
#include "nsIThreadManager.h"
#include "nsIThread.h"
#include "nsIRunnable.h"
#include "nsICancelableRunnable.h"
#include "nsStringGlue.h"
#include "nsCOMPtr.h"
#include "nsAutoPtr.h"
@ -263,6 +264,22 @@ protected:
}
};
// This class is designed to be subclassed.
class NS_COM_GLUE nsCancelableRunnable : public nsICancelableRunnable
{
public:
NS_DECL_ISUPPORTS
NS_DECL_NSIRUNNABLE
NS_DECL_NSICANCELABLERUNNABLE
nsCancelableRunnable() {
}
protected:
virtual ~nsCancelableRunnable() {
}
};
#undef IMETHOD_VISIBILITY
#define IMETHOD_VISIBILITY NS_VISIBILITY_HIDDEN

View File

@ -51,6 +51,7 @@ XPIDLSRCS = \
nsIThreadPool.idl \
nsITimer.idl \
nsIRunnable.idl \
nsICancelableRunnable.idl \
nsIEnvironment.idl \
nsIProcess.idl \
nsISupportsPriority.idl \

View File

@ -0,0 +1,24 @@
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/* 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 "nsIRunnable.idl"
/**
* Represents a task which can be dispatched to a thread for execution and
* which can be cancelled if necessary.
*/
[scriptable, uuid(de93dc4c-5eea-4eb7-b6d1-dbf1e0cef65c)]
interface nsICancelableRunnable : nsIRunnable
{
/**
* Cancels a pending task. If the task has already been executed this will
* be a no-op. Calling this method twice is considered an error.
*
* @throws NS_ERROR_UNEXPECTED
* Indicates that the runnable has already been canceled.
*/
void cancel();
};

View File

@ -5,8 +5,15 @@
#include "nsISupports.idl"
/**
* Represents a task which can be dispatched to a thread for execution.
*/
[scriptable, function, uuid(4a2abaf0-6886-11d3-9382-00104ba0fd40)]
interface nsIRunnable : nsISupports
{
/**
* The function implementing the task to be run.
*/
void run();
};