mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-03-01 22:07:41 +00:00
Bug 1594814 - move FileBlockCache over to a background thread; r=pehrsons
Sharing a common thread(pool) is better than spinning up a private thread. Differential Revision: https://phabricator.services.mozilla.com/D57146 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
2808b0a1c5
commit
3422b5f22b
@ -31,7 +31,7 @@ static void CloseFD(PRFileDesc* aFD) {
|
||||
}
|
||||
|
||||
void FileBlockCache::SetCacheFile(PRFileDesc* aFD) {
|
||||
LOG("SetFD(aFD=%p) mThread=%p", aFD, mThread.get());
|
||||
LOG("SetFD(aFD=%p) mBackgroundET=%p", aFD, mBackgroundET.get());
|
||||
|
||||
if (!aFD) {
|
||||
// Failed to get a temporary file. Shutdown.
|
||||
@ -44,7 +44,7 @@ void FileBlockCache::SetCacheFile(PRFileDesc* aFD) {
|
||||
}
|
||||
{
|
||||
MutexAutoLock lock(mDataMutex);
|
||||
if (mThread) {
|
||||
if (mBackgroundET) {
|
||||
// Still open, complete the initialization.
|
||||
mInitialized = true;
|
||||
if (mIsWriteScheduled) {
|
||||
@ -53,7 +53,7 @@ void FileBlockCache::SetCacheFile(PRFileDesc* aFD) {
|
||||
nsCOMPtr<nsIRunnable> event = mozilla::NewRunnableMethod(
|
||||
"FileBlockCache::SetCacheFile -> PerformBlockIOs", this,
|
||||
&FileBlockCache::PerformBlockIOs);
|
||||
mThread->Dispatch(event.forget(), NS_DISPATCH_NORMAL);
|
||||
mBackgroundET->Dispatch(event.forget(), NS_DISPATCH_EVENT_MAY_BLOCK);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@ -70,17 +70,16 @@ void FileBlockCache::SetCacheFile(PRFileDesc* aFD) {
|
||||
nsresult FileBlockCache::Init() {
|
||||
LOG("Init()");
|
||||
MutexAutoLock mon(mDataMutex);
|
||||
MOZ_ASSERT(!mThread);
|
||||
nsresult rv =
|
||||
NS_NewNamedThread("FileBlockCache", getter_AddRefs(mThread), nullptr,
|
||||
nsIThreadManager::kThreadPoolStackSize);
|
||||
MOZ_ASSERT(!mBackgroundET);
|
||||
nsresult rv = NS_CreateBackgroundTaskQueue("FileBlockCache",
|
||||
getter_AddRefs(mBackgroundET));
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (XRE_IsParentProcess()) {
|
||||
RefPtr<FileBlockCache> self = this;
|
||||
rv = mThread->Dispatch(
|
||||
rv = mBackgroundET->Dispatch(
|
||||
NS_NewRunnableFunction("FileBlockCache::Init",
|
||||
[self] {
|
||||
PRFileDesc* fd = nullptr;
|
||||
@ -92,7 +91,7 @@ nsresult FileBlockCache::Init() {
|
||||
self->Close();
|
||||
}
|
||||
}),
|
||||
NS_DISPATCH_NORMAL);
|
||||
NS_DISPATCH_EVENT_MAY_BLOCK);
|
||||
} else {
|
||||
// We must request a temporary file descriptor from the parent process.
|
||||
RefPtr<FileBlockCache> self = this;
|
||||
@ -110,12 +109,12 @@ nsresult FileBlockCache::Init() {
|
||||
void FileBlockCache::Flush() {
|
||||
LOG("Flush()");
|
||||
MutexAutoLock mon(mDataMutex);
|
||||
MOZ_ASSERT(mThread);
|
||||
MOZ_ASSERT(mBackgroundET);
|
||||
|
||||
// Dispatch a task so we won't clear the arrays while PerformBlockIOs() is
|
||||
// dropping the data lock and cause InvalidArrayIndex.
|
||||
RefPtr<FileBlockCache> self = this;
|
||||
mThread->Dispatch(NS_NewRunnableFunction("FileBlockCache::Flush", [self]() {
|
||||
mBackgroundET->Dispatch(NS_NewRunnableFunction("FileBlockCache::Flush", [self]() {
|
||||
MutexAutoLock mon(self->mDataMutex);
|
||||
// Just discard pending changes, assume MediaCache won't read from
|
||||
// blocks it hasn't written to.
|
||||
@ -159,13 +158,13 @@ FileBlockCache::~FileBlockCache() { Close(); }
|
||||
void FileBlockCache::Close() {
|
||||
LOG("Close()");
|
||||
|
||||
nsCOMPtr<nsIThread> thread;
|
||||
nsCOMPtr<nsISerialEventTarget> thread;
|
||||
{
|
||||
MutexAutoLock mon(mDataMutex);
|
||||
if (!mThread) {
|
||||
if (!mBackgroundET) {
|
||||
return;
|
||||
}
|
||||
thread.swap(mThread);
|
||||
thread.swap(mBackgroundET);
|
||||
}
|
||||
|
||||
PRFileDesc* fd;
|
||||
@ -176,8 +175,8 @@ void FileBlockCache::Close() {
|
||||
}
|
||||
|
||||
// Let the thread close the FD, and then trigger its own shutdown.
|
||||
// Note that mThread is now empty, so no other task will be posted there.
|
||||
// Also mThread and mFD are empty and therefore can be reused immediately.
|
||||
// Note that mBackgroundET is now empty, so no other task will be posted there.
|
||||
// Also mBackgroundET and mFD are empty and therefore can be reused immediately.
|
||||
nsresult rv = thread->Dispatch(
|
||||
NS_NewRunnableFunction(
|
||||
"FileBlockCache::Close",
|
||||
@ -185,19 +184,9 @@ void FileBlockCache::Close() {
|
||||
if (fd) {
|
||||
CloseFD(fd);
|
||||
}
|
||||
// We must shut down the thread in another
|
||||
// runnable. This is called
|
||||
// while we're shutting down the media cache, and
|
||||
// nsIThread::Shutdown()
|
||||
// can cause events to run before it completes,
|
||||
// which could end up
|
||||
// opening more streams, while the media cache is
|
||||
// shutting down and
|
||||
// releasing memory etc!
|
||||
nsCOMPtr<nsIRunnable> event = new ShutdownThreadEvent(thread);
|
||||
SystemGroup::Dispatch(TaskCategory::Other, event.forget());
|
||||
// No need to shutdown background task queues.
|
||||
}),
|
||||
NS_DISPATCH_NORMAL);
|
||||
NS_DISPATCH_EVENT_MAY_BLOCK);
|
||||
NS_ENSURE_SUCCESS_VOID(rv);
|
||||
}
|
||||
|
||||
@ -212,7 +201,7 @@ nsresult FileBlockCache::WriteBlock(uint32_t aBlockIndex,
|
||||
Span<const uint8_t> aData2) {
|
||||
MutexAutoLock mon(mDataMutex);
|
||||
|
||||
if (!mThread) {
|
||||
if (!mBackgroundET) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@ -241,7 +230,7 @@ nsresult FileBlockCache::WriteBlock(uint32_t aBlockIndex,
|
||||
|
||||
void FileBlockCache::EnsureWriteScheduled() {
|
||||
mDataMutex.AssertCurrentThreadOwns();
|
||||
MOZ_ASSERT(mThread);
|
||||
MOZ_ASSERT(mBackgroundET);
|
||||
|
||||
if (mIsWriteScheduled || mIsReading) {
|
||||
return;
|
||||
@ -255,7 +244,7 @@ void FileBlockCache::EnsureWriteScheduled() {
|
||||
nsCOMPtr<nsIRunnable> event = mozilla::NewRunnableMethod(
|
||||
"FileBlockCache::EnsureWriteScheduled -> PerformBlockIOs", this,
|
||||
&FileBlockCache::PerformBlockIOs);
|
||||
mThread->Dispatch(event.forget(), NS_DISPATCH_NORMAL);
|
||||
mBackgroundET->Dispatch(event.forget(), NS_DISPATCH_EVENT_MAY_BLOCK);
|
||||
}
|
||||
|
||||
nsresult FileBlockCache::Seek(int64_t aOffset) {
|
||||
@ -326,14 +315,14 @@ nsresult FileBlockCache::MoveBlockInFile(int32_t aSourceBlockIndex,
|
||||
}
|
||||
|
||||
void FileBlockCache::PerformBlockIOs() {
|
||||
MOZ_ASSERT(mThread->IsOnCurrentThread());
|
||||
MOZ_ASSERT(mBackgroundET->IsOnCurrentThread());
|
||||
MutexAutoLock mon(mDataMutex);
|
||||
NS_ASSERTION(mIsWriteScheduled, "Should report write running or scheduled.");
|
||||
|
||||
LOG("Run() mFD=%p mThread=%p", mFD, mThread.get());
|
||||
LOG("Run() mFD=%p mBackgroundET=%p", mFD, mBackgroundET.get());
|
||||
|
||||
while (!mChangeIndexList.empty()) {
|
||||
if (!mThread) {
|
||||
if (!mBackgroundET) {
|
||||
// We've been closed, abort, discarding unwritten changes.
|
||||
mIsWriteScheduled = false;
|
||||
return;
|
||||
@ -391,7 +380,7 @@ nsresult FileBlockCache::Read(int64_t aOffset, uint8_t* aData, int32_t aLength,
|
||||
int32_t* aBytes) {
|
||||
MutexAutoLock mon(mDataMutex);
|
||||
|
||||
if (!mThread || (aOffset / BLOCK_SIZE) > INT32_MAX) {
|
||||
if (!mBackgroundET || (aOffset / BLOCK_SIZE) > INT32_MAX) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
@ -462,7 +451,7 @@ nsresult FileBlockCache::MoveBlock(int32_t aSourceBlockIndex,
|
||||
int32_t aDestBlockIndex) {
|
||||
MutexAutoLock mon(mDataMutex);
|
||||
|
||||
if (!mThread) {
|
||||
if (!mBackgroundET) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
|
@ -171,14 +171,13 @@ class FileBlockCache : public MediaBlockCacheBase {
|
||||
// cached in memory waiting to be written, or this block is the target of a
|
||||
// block move.
|
||||
nsTArray<RefPtr<BlockChange> > mBlockChanges;
|
||||
// Thread upon which block writes and block moves are performed. This is
|
||||
// created upon open, and shutdown (asynchronously) upon close (on the
|
||||
// main thread).
|
||||
nsCOMPtr<nsIThread> mThread;
|
||||
// Event target upon which block writes and block moves are performed. This is
|
||||
// created upon open, and dropped on close.
|
||||
nsCOMPtr<nsISerialEventTarget> mBackgroundET;
|
||||
// Queue of pending block indexes that need to be written or moved.
|
||||
std::deque<int32_t> mChangeIndexList;
|
||||
// True if we've dispatched an event to commit all pending block changes
|
||||
// to file on mThread.
|
||||
// to file on mBackgroundET.
|
||||
bool mIsWriteScheduled;
|
||||
// True when a read is happening. Pending writes may be postponed, to give
|
||||
// higher priority to reads (which may be blocking the caller).
|
||||
|
Loading…
x
Reference in New Issue
Block a user