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:
danm%netscape.com 2001-06-06 02:30:07 +00:00
Родитель b95d9c0083
Коммит ebf0feed30
6 изменённых файлов: 60 добавлений и 73 удалений

45
netwerk/cache/src/nsCacheEntry.cpp поставляемый
Просмотреть файл

@ -30,6 +30,7 @@
#include "nsError.h" #include "nsError.h"
#include "nsICacheService.h" #include "nsICacheService.h"
#include "nsCache.h" #include "nsCache.h"
#include "nsCacheService.h"
#include "nsCacheDevice.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() nsCacheEntry::~nsCacheEntry()
{ {
delete mKey; delete mKey;
delete mMetaData; delete mMetaData;
if (IsStreamData()) return; if (IsStreamData()) return;
// proxy release of of memory cache nsISupports objects // proxy release of of memory cache nsISupports objects
if (!mData) { if (!mData) return;
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;
}
nsISupports * data = mData; 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 mData = nsnull; // release our reference before switching threads
PL_InitEvent(event, nsCacheService::ProxyObjectRelease(data, mThread);
data,
CacheElementReleaseEventHandler,
CacheElementReleaseDestroyHandler);
mEventQ->PostEvent(event);
} }
@ -128,6 +94,7 @@ nsCacheEntry::Create( const char * key,
return NS_OK; return NS_OK;
} }
void void
nsCacheEntry::Fetched() nsCacheEntry::Fetched()
{ {

7
netwerk/cache/src/nsCacheEntry.h поставляемый
Просмотреть файл

@ -34,8 +34,6 @@
#include "nsCOMPtr.h" #include "nsCOMPtr.h"
#include "nsString.h" #include "nsString.h"
#include "nsAReadableString.h" #include "nsAReadableString.h"
#include "nsIEventQueue.h"
class nsCacheDevice; class nsCacheDevice;
class nsCacheMetaData; class nsCacheMetaData;
@ -93,8 +91,7 @@ public:
void TouchData(); void TouchData();
nsIEventQueue * GetEventQ() { return mEventQ;} void SetThread(PRThread *aThread) { mThread = aThread; }
void SetEventQ(nsIEventQueue * eventQ) { mEventQ = dont_AddRef(eventQ);}
/** /**
* Meta data accessors * Meta data accessors
@ -230,7 +227,7 @@ private:
nsCacheDevice * mCacheDevice; // 4 nsCacheDevice * mCacheDevice; // 4
nsCOMPtr<nsISupports> mSecurityInfo; // nsCOMPtr<nsISupports> mSecurityInfo; //
nsCOMPtr<nsISupports> mData; // nsCOMPtr<nsISupports> mData; //
nsCOMPtr<nsIEventQueue> mEventQ; // event queue for mData (for mem object cache) PRThread * mThread;
nsCacheMetaData * mMetaData; // 4 nsCacheMetaData * mMetaData; // 4
PRCList mRequestQ; // 8 PRCList mRequestQ; // 8
PRCList mDescriptorQ; // 8 PRCList mDescriptorQ; // 8

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

@ -234,9 +234,6 @@ nsCacheEntryDescriptor::SetCacheElement(nsISupports * cacheElement)
if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE; if (!mCacheEntry) return NS_ERROR_NOT_AVAILABLE;
if (mCacheEntry->IsStreamData()) return NS_ERROR_CACHE_DATA_IS_STREAM; if (mCacheEntry->IsStreamData()) return NS_ERROR_CACHE_DATA_IS_STREAM;
mCacheEntry->SetData(cacheElement);
mCacheEntry->TouchData();
return nsCacheService::GlobalInstance()->SetCacheElement(mCacheEntry, cacheElement); return nsCacheService::GlobalInstance()->SetCacheElement(mCacheEntry, cacheElement);
} }

4
netwerk/cache/src/nsCacheRequest.h поставляемый
Просмотреть файл

@ -46,7 +46,7 @@ private:
: mKey(key), : mKey(key),
mInfo(0), mInfo(0),
mListener(listener), mListener(listener),
mEventQ(nsnull), mThread(nsnull),
mLock(nsnull), mLock(nsnull),
mCondVar(nsnull) mCondVar(nsnull)
{ {
@ -170,7 +170,7 @@ private:
nsCString * mKey; nsCString * mKey;
PRUint32 mInfo; PRUint32 mInfo;
nsCOMPtr<nsICacheListener> mListener; nsCOMPtr<nsICacheListener> mListener;
nsCOMPtr<nsIEventQueue> mEventQ; PRThread * mThread;
PRLock * mLock; PRLock * mLock;
PRCondVar * mCondVar; PRCondVar * mCondVar;
}; };

69
netwerk/cache/src/nsCacheService.cpp поставляемый
Просмотреть файл

@ -514,23 +514,9 @@ nsCacheService::CreateRequest(nsCacheSession * session,
if (!listener) return NS_OK; // we're sync, we're done. if (!listener) return NS_OK; // we're sync, we're done.
// get the nsIEventQueue for the request's thread // get the nsIEventQueue for the request's thread
nsresult rv; (*request)->mThread = PR_GetCurrentThread();
rv = mEventQService->ResolveEventQueue(NS_CURRENT_EVENTQ,
getter_AddRefs((*request)->mEventQ));
if (NS_FAILED(rv)) goto error;
if (!(*request)->mEventQ) {
rv = NS_ERROR_NOT_AVAILABLE;
goto error;
}
return NS_OK; return NS_OK;
error:
delete *request;
*request = nsnull;
return rv;
} }
@ -543,8 +529,11 @@ nsCacheService::NotifyListener(nsCacheRequest * request,
nsresult rv; nsresult rv;
nsCOMPtr<nsICacheListener> listenerProxy; nsCOMPtr<nsICacheListener> listenerProxy;
NS_ASSERTION(request->mEventQ, "no event queue for async request!"); NS_ASSERTION(request->mThread, "no thread set in async request!");
rv = mProxyObjectManager->GetProxyForObject(request->mEventQ, nsCOMPtr<nsIEventQueue> eventQ;
mEventQService->GetThreadEventQueue(request->mThread,
getter_AddRefs(eventQ));
rv = mProxyObjectManager->GetProxyForObject(eventQ,
NS_GET_IID(nsICacheListener), NS_GET_IID(nsICacheListener),
request->mListener, request->mListener,
PROXY_ASYNC|PROXY_ALWAYS, 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 void
nsCacheService::SetCacheDevicesEnabled(PRBool enableDisk, PRBool enableMemory) nsCacheService::SetCacheDevicesEnabled(PRBool enableDisk, PRBool enableMemory)
{ {
@ -882,12 +910,7 @@ nsCacheService::SetCacheDevicesEnabled(PRBool enableDisk, PRBool enableMemory)
nsresult nsresult
nsCacheService::SetCacheElement(nsCacheEntry * entry, nsISupports * element) nsCacheService::SetCacheElement(nsCacheEntry * entry, nsISupports * element)
{ {
nsresult rv; entry->SetThread(PR_GetCurrentThread());
nsIEventQueue * eventQ;
rv = mEventQService->ResolveEventQueue(NS_CURRENT_EVENTQ, &eventQ);
if (NS_FAILED(rv)) return rv;
entry->SetEventQ(eventQ);
entry->SetData(element); entry->SetData(element);
entry->TouchData(); entry->TouchData();
return NS_OK; return NS_OK;

5
netwerk/cache/src/nsCacheService.h поставляемый
Просмотреть файл

@ -98,12 +98,15 @@ public:
*/ */
static static
nsCacheService * GlobalInstance(void) { return gService; }; nsCacheService * GlobalInstance() { return gService; };
nsresult DoomEntry(nsCacheEntry * entry); nsresult DoomEntry(nsCacheEntry * entry);
nsresult DoomEntry_Locked(nsCacheEntry * entry); nsresult DoomEntry_Locked(nsCacheEntry * entry);
static
void ProxyObjectRelease(nsISupports * object, PRThread * thread);
/** /**
* Methods called by nsCachePrefObserver * Methods called by nsCachePrefObserver
*/ */