зеркало из https://github.com/mozilla/pjs.git
Bug 586859 - Move startupcache write off the main thread r=cjones a=2.0
This commit is contained in:
Родитель
01304e2dd4
Коммит
6cf529ec88
|
@ -64,6 +64,7 @@
|
|||
#include "nsZipArchive.h"
|
||||
#include "mozilla/Omnijar.h"
|
||||
#include "prenv.h"
|
||||
#include "mozilla/FunctionTimer.h"
|
||||
|
||||
#ifdef IS_BIG_ENDIAN
|
||||
#define SC_ENDIAN "big"
|
||||
|
@ -116,7 +117,7 @@ StartupCache* StartupCache::gStartupCache;
|
|||
PRBool StartupCache::gShutdownInitiated;
|
||||
|
||||
StartupCache::StartupCache()
|
||||
: mArchive(NULL), mStartupWriteInitiated(PR_FALSE) { }
|
||||
: mArchive(NULL), mStartupWriteInitiated(PR_FALSE), mWriteThread(NULL) {}
|
||||
|
||||
StartupCache::~StartupCache()
|
||||
{
|
||||
|
@ -203,6 +204,7 @@ StartupCache::Init()
|
|||
nsresult
|
||||
StartupCache::LoadArchive()
|
||||
{
|
||||
WaitOnWriteThread();
|
||||
PRBool exists;
|
||||
mArchive = NULL;
|
||||
nsresult rv = mFile->Exists(&exists);
|
||||
|
@ -218,6 +220,7 @@ StartupCache::LoadArchive()
|
|||
nsresult
|
||||
StartupCache::GetBuffer(const char* id, char** outbuf, PRUint32* length)
|
||||
{
|
||||
WaitOnWriteThread();
|
||||
if (!mStartupWriteInitiated) {
|
||||
CacheEntry* entry;
|
||||
nsDependentCString idStr(id);
|
||||
|
@ -257,6 +260,7 @@ StartupCache::GetBuffer(const char* id, char** outbuf, PRUint32* length)
|
|||
nsresult
|
||||
StartupCache::PutBuffer(const char* id, const char* inbuf, PRUint32 len)
|
||||
{
|
||||
WaitOnWriteThread();
|
||||
if (StartupCache::gShutdownInitiated) {
|
||||
return NS_ERROR_NOT_AVAILABLE;
|
||||
}
|
||||
|
@ -308,7 +312,7 @@ CacheCloseHelper(const nsACString& key, nsAutoPtr<CacheEntry>& data,
|
|||
NS_ASSERTION(NS_SUCCEEDED(rv) && hasEntry == PR_FALSE,
|
||||
"Existing entry in disk StartupCache.");
|
||||
#endif
|
||||
rv = writer->AddEntryStream(key, holder->time, PR_FALSE, stream, false);
|
||||
rv = writer->AddEntryStream(key, holder->time, PR_TRUE, stream, PR_FALSE);
|
||||
|
||||
if (NS_FAILED(rv)) {
|
||||
NS_WARNING("cache entry deleted but not written to disk.");
|
||||
|
@ -319,6 +323,7 @@ CacheCloseHelper(const nsACString& key, nsAutoPtr<CacheEntry>& data,
|
|||
void
|
||||
StartupCache::WriteToDisk()
|
||||
{
|
||||
WaitOnWriteThread();
|
||||
nsresult rv;
|
||||
mStartupWriteInitiated = PR_TRUE;
|
||||
|
||||
|
@ -352,7 +357,7 @@ StartupCache::WriteToDisk()
|
|||
// Close the archive so Windows doesn't choke.
|
||||
mArchive = NULL;
|
||||
zipW->Close();
|
||||
|
||||
|
||||
// our reader's view of the archive is outdated now, reload it.
|
||||
LoadArchive();
|
||||
|
||||
|
@ -362,17 +367,52 @@ StartupCache::WriteToDisk()
|
|||
void
|
||||
StartupCache::InvalidateCache()
|
||||
{
|
||||
WaitOnWriteThread();
|
||||
mTable.Clear();
|
||||
mArchive = NULL;
|
||||
mFile->Remove(false);
|
||||
LoadArchive();
|
||||
}
|
||||
|
||||
/*
|
||||
* WaitOnWriteThread() is called from a main thread to wait for the worker
|
||||
* thread to finish. However since the same code is used in the worker thread and
|
||||
* main thread, the worker thread can also call WaitOnWriteThread() which is a no-op.
|
||||
*/
|
||||
void
|
||||
StartupCache::WaitOnWriteThread()
|
||||
{
|
||||
PRThread* writeThread = mWriteThread;
|
||||
if (!writeThread || writeThread == PR_GetCurrentThread())
|
||||
return;
|
||||
|
||||
NS_TIME_FUNCTION_MIN(30);
|
||||
//NS_WARNING("Waiting on startupcache write");
|
||||
PR_JoinThread(writeThread);
|
||||
mWriteThread = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
StartupCache::ThreadedWrite(void *aClosure)
|
||||
{
|
||||
gStartupCache->WriteToDisk();
|
||||
}
|
||||
|
||||
/*
|
||||
* The write-thread is spawned on a timeout(which is reset with every write). This
|
||||
* can avoid a slow shutdown. After writing out the cache, the zipreader is
|
||||
* reloaded on the worker thread.
|
||||
*/
|
||||
void
|
||||
StartupCache::WriteTimeout(nsITimer *aTimer, void *aClosure)
|
||||
{
|
||||
StartupCache* sc = (StartupCache*) aClosure;
|
||||
sc->WriteToDisk();
|
||||
gStartupCache->mWriteThread = PR_CreateThread(PR_USER_THREAD,
|
||||
StartupCache::ThreadedWrite,
|
||||
NULL,
|
||||
PR_PRIORITY_NORMAL,
|
||||
PR_LOCAL_THREAD,
|
||||
PR_JOINABLE_THREAD,
|
||||
0);
|
||||
}
|
||||
|
||||
// We don't want to refcount StartupCache, so we'll just
|
||||
|
@ -382,15 +422,18 @@ NS_IMPL_THREADSAFE_ISUPPORTS1(StartupCacheListener, nsIObserver)
|
|||
nsresult
|
||||
StartupCacheListener::Observe(nsISupports *subject, const char* topic, const PRUnichar* data)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
StartupCache* sc = StartupCache::GetSingleton();
|
||||
if (!sc)
|
||||
return NS_OK;
|
||||
|
||||
if (strcmp(topic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0) {
|
||||
// Do not leave the thread running past xpcom shutdown
|
||||
sc->WaitOnWriteThread();
|
||||
StartupCache::gShutdownInitiated = PR_TRUE;
|
||||
} else if (strcmp(topic, "startupcache-invalidate") == 0) {
|
||||
StartupCache* sc = StartupCache::GetSingleton();
|
||||
if (sc)
|
||||
sc->InvalidateCache();
|
||||
sc->InvalidateCache();
|
||||
}
|
||||
return rv;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
|
@ -582,6 +625,7 @@ StartupCacheWrapper::StartupWriteComplete(PRBool *complete)
|
|||
if (!sc) {
|
||||
return NS_ERROR_NOT_INITIALIZED;
|
||||
}
|
||||
sc->WaitOnWriteThread();
|
||||
*complete = sc->mStartupWriteInitiated && sc->mTable.Count() == 0;
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче