зеркало из https://github.com/mozilla/pjs.git
nsCacheEntry now asks nsCacheService to release its data, and therefore no longer holds a strong ref to its event queue. bugscape bug 4890, bugzilla bug 84247 code=gordon,me r=beard,sfraser a=clayton,chofmann
This commit is contained in:
Родитель
f2b48ea628
Коммит
b87a4d3a8f
|
@ -30,6 +30,7 @@
|
|||
#include "nsError.h"
|
||||
#include "nsICacheService.h"
|
||||
#include "nsCache.h"
|
||||
#include "nsCacheService.h"
|
||||
#include "nsCacheDevice.h"
|
||||
|
||||
|
||||
|
@ -56,56 +57,21 @@ nsCacheEntry::nsCacheEntry(nsCString * key,
|
|||
}
|
||||
|
||||
|
||||
static void* PR_CALLBACK
|
||||
CacheElementReleaseEventHandler(PLEvent *self)
|
||||
{
|
||||
nsISupports * element = (nsISupports *)PL_GetEventOwner(self);
|
||||
NS_RELEASE(element);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void PR_CALLBACK
|
||||
CacheElementReleaseDestroyHandler(PLEvent *self)
|
||||
{
|
||||
delete self;
|
||||
}
|
||||
|
||||
|
||||
nsCacheEntry::~nsCacheEntry()
|
||||
{
|
||||
delete mKey;
|
||||
delete mMetaData;
|
||||
|
||||
if (IsStreamData()) return;
|
||||
if (IsStreamData()) return;
|
||||
|
||||
// proxy release of of memory cache nsISupports objects
|
||||
if (!mData) {
|
||||
NS_ASSERTION(!mEventQ, "### ~nsCacheEntry: mEventQ but no mData");
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mEventQ) {
|
||||
NS_ASSERTION(!mData, "### ~nsCacheEntry: mData, but no eventQ");
|
||||
return;
|
||||
}
|
||||
|
||||
PLEvent * event = new PLEvent;
|
||||
if (!event) {
|
||||
// XXX warning
|
||||
return;
|
||||
}
|
||||
if (!mData) return;
|
||||
|
||||
nsISupports * data = mData;
|
||||
NS_ADDREF(data); // this reference will be owned by the event
|
||||
NS_ADDREF(data); // this reference will be owned by the proxy
|
||||
mData = nsnull; // release our reference before switching threads
|
||||
|
||||
PL_InitEvent(event,
|
||||
data,
|
||||
CacheElementReleaseEventHandler,
|
||||
CacheElementReleaseDestroyHandler);
|
||||
|
||||
mEventQ->PostEvent(event);
|
||||
nsCacheService::ProxyObjectRelease(data, mThread);
|
||||
}
|
||||
|
||||
|
||||
|
@ -128,6 +94,7 @@ nsCacheEntry::Create( const char * key,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nsCacheEntry::Fetched()
|
||||
{
|
||||
|
|
|
@ -34,8 +34,6 @@
|
|||
#include "nsCOMPtr.h"
|
||||
#include "nsString.h"
|
||||
#include "nsAReadableString.h"
|
||||
#include "nsIEventQueue.h"
|
||||
|
||||
|
||||
class nsCacheDevice;
|
||||
class nsCacheMetaData;
|
||||
|
@ -93,8 +91,7 @@ public:
|
|||
|
||||
void TouchData();
|
||||
|
||||
nsIEventQueue * GetEventQ() { return mEventQ;}
|
||||
void SetEventQ(nsIEventQueue * eventQ) { mEventQ = dont_AddRef(eventQ);}
|
||||
void SetThread(PRThread *aThread) { mThread = aThread; }
|
||||
|
||||
/**
|
||||
* Meta data accessors
|
||||
|
@ -230,7 +227,7 @@ private:
|
|||
nsCacheDevice * mCacheDevice; // 4
|
||||
nsCOMPtr<nsISupports> mSecurityInfo; //
|
||||
nsCOMPtr<nsISupports> mData; //
|
||||
nsCOMPtr<nsIEventQueue> mEventQ; // event queue for mData (for mem object cache)
|
||||
PRThread * mThread;
|
||||
nsCacheMetaData * mMetaData; // 4
|
||||
PRCList mRequestQ; // 8
|
||||
PRCList mDescriptorQ; // 8
|
||||
|
|
|
@ -234,9 +234,6 @@ nsCacheEntryDescriptor::SetCacheElement(nsISupports * cacheElement)
|
|||
if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE;
|
||||
if (mCacheEntry->IsStreamData()) return NS_ERROR_CACHE_DATA_IS_STREAM;
|
||||
|
||||
mCacheEntry->SetData(cacheElement);
|
||||
mCacheEntry->TouchData();
|
||||
|
||||
return nsCacheService::GlobalInstance()->SetCacheElement(mCacheEntry, cacheElement);
|
||||
}
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ private:
|
|||
: mKey(key),
|
||||
mInfo(0),
|
||||
mListener(listener),
|
||||
mEventQ(nsnull),
|
||||
mThread(nsnull),
|
||||
mLock(nsnull),
|
||||
mCondVar(nsnull)
|
||||
{
|
||||
|
@ -170,7 +170,7 @@ private:
|
|||
nsCString * mKey;
|
||||
PRUint32 mInfo;
|
||||
nsCOMPtr<nsICacheListener> mListener;
|
||||
nsCOMPtr<nsIEventQueue> mEventQ;
|
||||
PRThread * mThread;
|
||||
PRLock * mLock;
|
||||
PRCondVar * mCondVar;
|
||||
};
|
||||
|
|
|
@ -514,23 +514,9 @@ nsCacheService::CreateRequest(nsCacheSession * session,
|
|||
if (!listener) return NS_OK; // we're sync, we're done.
|
||||
|
||||
// get the nsIEventQueue for the request's thread
|
||||
nsresult rv;
|
||||
rv = mEventQService->ResolveEventQueue(NS_CURRENT_EVENTQ,
|
||||
getter_AddRefs((*request)->mEventQ));
|
||||
if (NS_FAILED(rv)) goto error;
|
||||
(*request)->mThread = PR_GetCurrentThread();
|
||||
|
||||
|
||||
if (!(*request)->mEventQ) {
|
||||
rv = NS_ERROR_NOT_AVAILABLE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
|
||||
error:
|
||||
delete *request;
|
||||
*request = nsnull;
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
|
@ -543,8 +529,11 @@ nsCacheService::NotifyListener(nsCacheRequest * request,
|
|||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsICacheListener> listenerProxy;
|
||||
NS_ASSERTION(request->mEventQ, "no event queue for async request!");
|
||||
rv = mProxyObjectManager->GetProxyForObject(request->mEventQ,
|
||||
NS_ASSERTION(request->mThread, "no thread set in async request!");
|
||||
nsCOMPtr<nsIEventQueue> eventQ;
|
||||
mEventQService->GetThreadEventQueue(request->mThread,
|
||||
getter_AddRefs(eventQ));
|
||||
rv = mProxyObjectManager->GetProxyForObject(eventQ,
|
||||
NS_GET_IID(nsICacheListener),
|
||||
request->mListener,
|
||||
PROXY_ASYNC|PROXY_ALWAYS,
|
||||
|
@ -859,6 +848,45 @@ nsCacheService::DoomEntry_Locked(nsCacheEntry * entry)
|
|||
}
|
||||
|
||||
|
||||
static void* PR_CALLBACK
|
||||
EventHandler(PLEvent *self)
|
||||
{
|
||||
nsISupports * object = (nsISupports *)PL_GetEventOwner(self);
|
||||
NS_RELEASE(object);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static void PR_CALLBACK
|
||||
DestroyHandler(PLEvent *self)
|
||||
{
|
||||
delete self;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nsCacheService::ProxyObjectRelease(nsISupports * object, PRThread * thread)
|
||||
{
|
||||
NS_ASSERTION(gService, "nsCacheService not initialized");
|
||||
NS_ASSERTION(thread, "no thread");
|
||||
// XXX if thread == current thread, we could avoid posting an event,
|
||||
// XXX by add this object to a queue and release it when the cache service is unlocked.
|
||||
|
||||
nsCOMPtr<nsIEventQueue> eventQ;
|
||||
gService->mEventQService->GetThreadEventQueue(thread, getter_AddRefs(eventQ));
|
||||
NS_ASSERTION(eventQ, "no event queue for thread");
|
||||
if (!eventQ) return;
|
||||
|
||||
PLEvent * event = new PLEvent;
|
||||
if (!event) {
|
||||
// XXX warning
|
||||
return;
|
||||
}
|
||||
PL_InitEvent(event, object, EventHandler, DestroyHandler);
|
||||
eventQ->PostEvent(event);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
nsCacheService::SetCacheDevicesEnabled(PRBool enableDisk, PRBool enableMemory)
|
||||
{
|
||||
|
@ -882,12 +910,7 @@ nsCacheService::SetCacheDevicesEnabled(PRBool enableDisk, PRBool enableMemory)
|
|||
nsresult
|
||||
nsCacheService::SetCacheElement(nsCacheEntry * entry, nsISupports * element)
|
||||
{
|
||||
nsresult rv;
|
||||
nsIEventQueue * eventQ;
|
||||
rv = mEventQService->ResolveEventQueue(NS_CURRENT_EVENTQ, &eventQ);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
entry->SetEventQ(eventQ);
|
||||
entry->SetThread(PR_GetCurrentThread());
|
||||
entry->SetData(element);
|
||||
entry->TouchData();
|
||||
return NS_OK;
|
||||
|
|
|
@ -98,12 +98,15 @@ public:
|
|||
*/
|
||||
|
||||
static
|
||||
nsCacheService * GlobalInstance(void) { return gService; };
|
||||
nsCacheService * GlobalInstance() { return gService; };
|
||||
|
||||
nsresult DoomEntry(nsCacheEntry * entry);
|
||||
|
||||
nsresult DoomEntry_Locked(nsCacheEntry * entry);
|
||||
|
||||
static
|
||||
void ProxyObjectRelease(nsISupports * object, PRThread * thread);
|
||||
|
||||
/**
|
||||
* Methods called by nsCachePrefObserver
|
||||
*/
|
||||
|
|
Загрузка…
Ссылка в новой задаче