fixes bug 278531 "generic request prioritization (loadgroup prioritization)" r=biesi sr=bzbarsky

This commit is contained in:
darin%meer.net 2005-02-21 20:58:01 +00:00
Родитель ce15a1d673
Коммит f2311e1369
14 изменённых файлов: 316 добавлений и 19 удалений

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

@ -57,6 +57,7 @@
#include "nsIIOService.h"
#include "nsIURL.h"
#include "nsILoadGroup.h"
#include "nsISupportsPriority.h"
#include "nsIServiceManager.h"
#include "nsNetUtil.h"
#include "nsIView.h"
@ -300,6 +301,11 @@ nsImageFrame::Init(nsPresContext* aPresContext,
PRUint32 currentLoadStatus = imgIRequest::STATUS_ERROR;
if (currentRequest) {
currentRequest->GetImageStatus(&currentLoadStatus);
// Give image loads associated with an image frame a small priority boost!
nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(currentRequest);
if (p)
p->BumpPriority(-1);
}
if (currentLoadStatus & imgIRequest::STATUS_ERROR) {

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

@ -175,7 +175,8 @@ static nsresult NewImageChannel(nsIChannel **aResult,
nsIURI *aURI,
nsIURI *aInitialDocumentURI,
nsIURI *aReferringURI,
nsILoadGroup *aLoadGroup, nsLoadFlags aLoadFlags)
nsILoadGroup *aLoadGroup,
nsLoadFlags aLoadFlags)
{
nsresult rv;
nsCOMPtr<nsIChannel> newChannel;
@ -222,6 +223,17 @@ static nsresult NewImageChannel(nsIChannel **aResult,
newHttpChannel->SetReferrer(aReferringURI);
}
// Image channels are loaded by default with reduced priority.
nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(*aResult);
if (p) {
PRUint32 priority = nsISupportsPriority::PRIORITY_LOW;
if (aLoadFlags & nsIRequest::LOAD_BACKGROUND)
++priority; // further reduce priority for background loads
p->BumpPriority(priority);
}
return NS_OK;
}
@ -914,7 +926,7 @@ void imgCacheValidator::AddProxy(imgRequestProxy *aProxy)
// the network.
aProxy->AddToLoadGroup();
mProxies.AppendElement(aProxy);
mProxies.AppendElement(NS_STATIC_CAST(imgIRequest *, aProxy));
}
/** nsIRequestObserver methods **/

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

@ -326,6 +326,32 @@ PRBool imgRequest::HaveProxyWithObserver(imgRequestProxy* aProxyToIgnore) const
return PR_FALSE;
}
PRInt32 imgRequest::Priority() const
{
PRInt32 priority = nsISupportsPriority::PRIORITY_NORMAL;
nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(mChannel);
if (p)
p->GetPriority(&priority);
return priority;
}
void imgRequest::BumpPriority(imgRequestProxy *proxy, PRInt32 delta)
{
// only the first proxy is allowed to modify the priority of this image load.
//
// XXX(darin): this is probably not the most optimal algorithm as we may want
// to increase the priority of requests that have a lot of proxies. the key
// concern though is that image loads remain lower priority than other pieces
// of content such as link clicks, CSS, and JS.
//
if (mObservers[0] != proxy)
return;
nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(mChannel);
if (p)
p->BumpPriority(delta);
}
/** imgILoad methods **/
NS_IMETHODIMP imgRequest::SetImage(imgIContainer *aImage)

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

@ -117,6 +117,14 @@ private:
// aProxyToIgnore, has an observer. aProxyToIgnore may be null.
PRBool HaveProxyWithObserver(imgRequestProxy* aProxyToIgnore) const;
// Return the priority of the underlying network request, or return
// PRIORITY_NORMAL if it doesn't support nsISupportsPriority.
PRInt32 Priority() const;
// Bump the priority of the underlying network request by the given delta
// on behalf of the given proxy.
void BumpPriority(imgRequestProxy *aProxy, PRInt32 aDelta);
public:
NS_DECL_IMGILOAD
NS_DECL_IMGIDECODEROBSERVER

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

@ -55,7 +55,8 @@
#include "nspr.h"
NS_IMPL_THREADSAFE_ISUPPORTS2(imgRequestProxy, imgIRequest, nsIRequest)
NS_IMPL_THREADSAFE_ISUPPORTS3(imgRequestProxy, imgIRequest, nsIRequest,
nsISupportsPriority)
imgRequestProxy::imgRequestProxy() :
mOwner(nsnull),
@ -353,6 +354,29 @@ NS_IMETHODIMP imgRequestProxy::Clone(imgIDecoderObserver* aObserver,
return NS_OK;
}
/** nsISupportsPriority methods **/
NS_IMETHODIMP imgRequestProxy::GetPriority(PRInt32 *priority)
{
NS_ENSURE_STATE(mOwner);
*priority = mOwner->Priority();
return NS_OK;
}
NS_IMETHODIMP imgRequestProxy::SetPriority(PRInt32 priority)
{
NS_ENSURE_STATE(mOwner);
mOwner->BumpPriority(this, priority - mOwner->Priority());
return NS_OK;
}
NS_IMETHODIMP imgRequestProxy::BumpPriority(PRInt32 priority)
{
NS_ENSURE_STATE(mOwner);
mOwner->BumpPriority(this, priority);
return NS_OK;
}
/** imgIContainerObserver methods **/
void imgRequestProxy::FrameChanged(imgIContainer *container, gfxIImageFrame *newframe, nsIntRect * dirtyRect)

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

@ -45,6 +45,7 @@
#include "nsIRequestObserver.h"
#include "nsIChannel.h"
#include "nsILoadGroup.h"
#include "nsISupportsPriority.h"
#include "nsCOMPtr.h"
#include "imgRequest.h"
@ -59,12 +60,13 @@
{0x8f, 0x65, 0x9c, 0x46, 0x2e, 0xe2, 0xbc, 0x95} \
}
class imgRequestProxy : public imgIRequest
class imgRequestProxy : public imgIRequest, public nsISupportsPriority
{
public:
NS_DECL_ISUPPORTS
NS_DECL_IMGIREQUEST
NS_DECL_NSIREQUEST
NS_DECL_NSISUPPORTSPRIORITY
imgRequestProxy();
virtual ~imgRequestProxy();

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

@ -123,6 +123,26 @@ RequestHashInitEntry(PLDHashTable *table, PLDHashEntryHdr *entry,
}
static void
RescheduleRequest(nsIRequest *aRequest, PRInt32 delta)
{
nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(aRequest);
if (p)
p->BumpPriority(delta);
}
PR_STATIC_CALLBACK(PLDHashOperator)
RescheduleRequests(PLDHashTable *table, PLDHashEntryHdr *hdr,
PRUint32 number, void *arg)
{
RequestMapEntry *e = NS_STATIC_CAST(RequestMapEntry *, hdr);
PRInt32 *delta = NS_STATIC_CAST(PRInt32 *, arg);
RescheduleRequest(e->mKey, *delta);
return PL_DHASH_NEXT;
}
nsLoadGroup::nsLoadGroup(nsISupports* outer)
: mForegroundCount(0)
, mLoadFlags(LOAD_NORMAL)
@ -229,6 +249,9 @@ nsLoadGroup::AggregatedQueryInterface(const nsIID& aIID, void** aInstancePtr)
aIID.Equals(NS_GET_IID(nsISupports))) {
*aInstancePtr = NS_STATIC_CAST(nsILoadGroup*, this);
}
else if (aIID.Equals(NS_GET_IID(nsISupportsPriority))) {
*aInstancePtr = NS_STATIC_CAST(nsISupportsPriority*,this);
}
else if (aIID.Equals(NS_GET_IID(nsISupportsWeakReference))) {
*aInstancePtr = NS_STATIC_CAST(nsISupportsWeakReference*,this);
}
@ -300,7 +323,7 @@ AppendRequestsToVoidArray(PLDHashTable *table, PLDHashEntryHdr *hdr,
// nsVoidArray enumeration callback that releases all items in the
// nsVoidArray
PR_STATIC_CALLBACK(PRBool)
ReleaseVoidArrayItems(void* aElement, void *aData)
ReleaseVoidArrayItems(void *aElement, void *aData)
{
nsISupports *s = NS_STATIC_CAST(nsISupports *, aElement);
@ -602,6 +625,9 @@ nsLoadGroup::AddRequest(nsIRequest *request, nsISupports* ctxt)
return NS_ERROR_OUT_OF_MEMORY;
}
if (mPriority != 0)
RescheduleRequest(request, mPriority);
if (!(flags & nsIRequest::LOAD_BACKGROUND)) {
// Update the count of foreground URIs..
mForegroundCount += 1;
@ -684,6 +710,10 @@ nsLoadGroup::RemoveRequest(nsIRequest *request, nsISupports* ctxt,
PL_DHashTableRawRemove(&mRequests, entry);
// Undo any group priority delta...
if (mPriority != 0)
RescheduleRequest(request, -mPriority);
nsLoadFlags flags;
rv = request->GetLoadFlags(&flags);
if (NS_FAILED(rv)) return rv;
@ -794,6 +824,33 @@ nsLoadGroup::SetNotificationCallbacks(nsIInterfaceRequestor *aCallbacks)
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
// nsISupportsPriority methods:
NS_IMETHODIMP
nsLoadGroup::GetPriority(PRInt32 *aValue)
{
*aValue = mPriority;
return NS_OK;
}
NS_IMETHODIMP
nsLoadGroup::SetPriority(PRInt32 aValue)
{
return BumpPriority(aValue - mPriority);
}
NS_IMETHODIMP
nsLoadGroup::BumpPriority(PRInt32 aDelta)
{
// Update the priority for each request that supports nsISupportsPriority
if (aDelta != 0) {
mPriority += aDelta;
PL_DHashTableEnumerate(&mRequests, RescheduleRequests, &aDelta);
}
return NS_OK;
}
////////////////////////////////////////////////////////////////////////////////
nsresult nsLoadGroup::MergeLoadFlags(nsIRequest *aRequest, nsLoadFlags& outFlags)

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

@ -47,11 +47,13 @@
#include "nsWeakReference.h"
#include "nsIInterfaceRequestor.h"
#include "nsIInterfaceRequestorUtils.h"
#include "nsISupportsPriority.h"
#include "pldhash.h"
class nsISupportsArray;
class nsLoadGroup : public nsILoadGroup,
public nsISupportsPriority,
public nsSupportsWeakReference
{
public:
@ -65,6 +67,10 @@ public:
// nsILoadGroup methods:
NS_DECL_NSILOADGROUP
////////////////////////////////////////////////////////////////////////////
// nsISupportsPriority methods:
NS_DECL_NSISUPPORTSPRIORITY
////////////////////////////////////////////////////////////////////////////
// nsLoadGroup methods:
@ -92,6 +98,7 @@ protected:
nsWeakPtr mObserver;
nsresult mStatus;
PRInt32 mPriority;
PRBool mIsCanceling;
};

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

@ -45,7 +45,7 @@ interface nsIProxyInfo;
* using any feature exposed by this interface, be aware that this interface
* will change and you will be broken. You have been warned.
*/
[scriptable, uuid(ae9dce68-c27c-44f1-b41d-462f5e470945)]
[scriptable, uuid(f3764874-ed7e-4873-883c-11d67a4e3638)]
interface nsIHttpChannelInternal : nsISupports
{
/**
@ -77,11 +77,4 @@ interface nsIHttpChannelInternal : nsISupports
* Get the proxy info in use by the channel.
*/
readonly attribute nsIProxyInfo proxyInfo;
/**
* Get or set the relative priority for this HTTP channel. Smaller values
* have higher priority. Negative values are allowed, and the default
* priority is 0.
*/
attribute short priority;
};

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

@ -96,7 +96,7 @@ nsHttpChannel::nsHttpChannel()
, mStatus(NS_OK)
, mLogicalOffset(0)
, mCaps(0)
, mPriority(0)
, mPriority(PRIORITY_NORMAL)
, mCachedResponseHead(nsnull)
, mCacheAccess(0)
, mPostID(0)
@ -2811,6 +2811,7 @@ NS_INTERFACE_MAP_BEGIN(nsHttpChannel)
NS_INTERFACE_MAP_ENTRY(nsIHttpChannelInternal)
NS_INTERFACE_MAP_ENTRY(nsIResumableChannel)
NS_INTERFACE_MAP_ENTRY(nsITransportEventSink)
NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)
if (aIID.Equals(NS_GET_IID(nsIProperties))) {
if (!mProperties) {
mProperties =
@ -3640,18 +3641,32 @@ nsHttpChannel::GetProxyInfo(nsIProxyInfo **result)
return NS_OK;
}
//-----------------------------------------------------------------------------
// nsHttpChannel::nsISupportsPriority
//-----------------------------------------------------------------------------
NS_IMETHODIMP
nsHttpChannel::GetPriority(PRInt16 *value)
nsHttpChannel::GetPriority(PRInt32 *value)
{
*value = mPriority;
return NS_OK;
}
NS_IMETHODIMP
nsHttpChannel::SetPriority(PRInt16 value)
nsHttpChannel::SetPriority(PRInt32 value)
{
mPriority = value;
return NS_OK;
PRInt16 newValue = CLAMP(value, PR_INT16_MIN, PR_INT16_MAX);
if (mPriority == newValue)
return NS_OK;
mPriority = newValue;
if (mTransaction)
gHttpHandler->RescheduleTransaction(mTransaction, mPriority);
}
NS_IMETHODIMP
nsHttpChannel::BumpPriority(PRInt32 delta)
{
return SetPriority(mPriority + delta);
}
//-----------------------------------------------------------------------------

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

@ -71,6 +71,7 @@
#include "nsIInputStreamPump.h"
#include "nsIPrompt.h"
#include "nsIResumableChannel.h"
#include "nsISupportsPriority.h"
class nsHttpResponseHead;
class nsAHttpConnection;
@ -90,6 +91,7 @@ class nsHttpChannel : public nsIHttpChannel
, public nsIEncodedChannel
, public nsITransportEventSink
, public nsIResumableChannel
, public nsISupportsPriority
{
public:
NS_DECL_ISUPPORTS
@ -105,6 +107,7 @@ public:
NS_DECL_NSIHTTPCHANNELINTERNAL
NS_DECL_NSITRANSPORTEVENTSINK
NS_DECL_NSIRESUMABLECHANNEL
NS_DECL_NSISUPPORTSPRIORITY
nsHttpChannel();
virtual ~nsHttpChannel();

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

@ -232,6 +232,7 @@ NS_INTERFACE_MAP_BEGIN(nsDocLoader)
NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)
NS_INTERFACE_MAP_ENTRY(nsIHttpEventSink)
NS_INTERFACE_MAP_ENTRY(nsISecurityEventSink)
NS_INTERFACE_MAP_ENTRY(nsISupportsPriority)
if (aIID.Equals(kThisImplCID))
foundInterface = NS_STATIC_CAST(nsIDocumentLoader *, this);
else
@ -1467,6 +1468,69 @@ NS_IMETHODIMP nsDocLoader::OnSecurityChange(nsISupports * aContext,
return NS_OK;
}
/*
* Implementation of nsISupportsPriority methods...
*
* The priority of the DocLoader _is_ the priority of its LoadGroup.
*
* XXX(darin): Once we start storing loadgroups in loadgroups, this code will
* go away.
*/
NS_IMETHODIMP nsDocLoader::GetPriority(PRInt32 *aPriority)
{
nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(mLoadGroup);
if (p)
return p->GetPriority(aPriority);
*aPriority = 0;
return NS_OK;
}
NS_IMETHODIMP nsDocLoader::SetPriority(PRInt32 aPriority)
{
PR_LOG(gDocLoaderLog, PR_LOG_DEBUG,
("DocLoader:%p: SetPriority(%d) called\n", this, aPriority));
nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(mLoadGroup);
if (p)
p->SetPriority(aPriority);
PRInt32 count = mChildList.Count();
nsDocLoader *loader;
for (PRInt32 i=0; i < count; i++) {
loader = NS_STATIC_CAST(nsDocLoader*, ChildAt(i));
if (loader) {
loader->SetPriority(aPriority);
}
}
return NS_OK;
}
NS_IMETHODIMP nsDocLoader::BumpPriority(PRInt32 aDelta)
{
PR_LOG(gDocLoaderLog, PR_LOG_DEBUG,
("DocLoader:%p: BumpPriority(%d) called\n", this, aDelta));
nsCOMPtr<nsISupportsPriority> p = do_QueryInterface(mLoadGroup);
if (p)
p->BumpPriority(aDelta);
PRInt32 count = mChildList.Count();
nsDocLoader *loader;
for (PRInt32 i=0; i < count; i++) {
loader = NS_STATIC_CAST(nsDocLoader*, ChildAt(i));
if (loader) {
loader->BumpPriority(aDelta);
}
}
return NS_OK;
}

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

@ -56,6 +56,7 @@
#include "nsIInterfaceRequestorUtils.h"
#include "nsIHttpEventSink.h"
#include "nsISecurityEventSink.h"
#include "nsISupportsPriority.h"
#include "nsInt64.h"
#include "nsCOMPtr.h"
#include "pldhash.h"
@ -82,7 +83,8 @@ class nsDocLoader : public nsIDocumentLoader,
public nsIWebProgress,
public nsIInterfaceRequestor,
public nsIHttpEventSink,
public nsISecurityEventSink
public nsISecurityEventSink,
public nsISupportsPriority
{
public:
NS_DEFINE_STATIC_IID_ACCESSOR(NS_THIS_DOCLOADER_IMPL_CID);
@ -114,6 +116,7 @@ public:
NS_DECL_NSIINTERFACEREQUESTOR
NS_DECL_NSIHTTPEVENTSINK
NS_DECL_NSISUPPORTSPRIORITY
// Implementation specific methods...

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

@ -0,0 +1,77 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is Mozilla.
*
* The Initial Developer of the Original Code is
* Darin Fisher <darin@meer.net>.
* Portions created by the Initial Developer are Copyright (C) 2004
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
/**
* This interface exposes the general notion of a scheduled object with a
* integral priority value. Following UNIX conventions, smaller (and possibly
* negative) values have higher priority.
*
* This interface does not strictly define what happens when the priority of an
* object is changed. An implementation of this interface is free to define
* the side-effects of changing the priority of an object. In some cases,
* changing the priority of an object may be disallowed (resulting in an
* exception being thrown) or may simply be ignored.
*/
[scriptable, uuid(aa578b44-abd5-4c19-8b14-36d4de6fdc36)]
interface nsISupportsPriority : nsISupports
{
/**
* Typical priority values.
*/
const long PRIORITY_HIGHEST = -20;
const long PRIORITY_HIGH = -10;
const long PRIORITY_NORMAL = 0;
const long PRIORITY_LOW = 10;
const long PRIORITY_LOWEST = 20;
/**
* This attribute may be modified to change the priority of this object. The
* implementation of this interface is free to truncate a given priority
* value to whatever limits are appropriate. Typically, this attribute is
* initialized to PRIORITY_NORMAL, but implementations may choose to assign a
* different initial value.
*/
attribute long priority;
/**
* This method adjusts the priority attribute by a given delta. It helps
* reduce the amount of coding required to increment or decrement the value
* of the priority attribute.
*/
void bumpPriority(in long delta);
};