Bug 1371882 - Remove FileBlockCache's dependency on Runnable - r=cpearce
This is necessary before we can make FileBlockCache depend on another
ref-counted base in the following patch.
MozReview-Commit-ID: 8bfNwQhY8k0
--- a/dom/media/FileBlockCache.cpp
+++ b/dom/media/FileBlockCache.cpp
@@ -47,17 +47,21 @@ FileBlockCache::SetCacheFile(PRFileDesc*
{
MutexAutoLock lock(mDataMutex);
if (mIsOpen) {
// Still open, complete the initialization.
mInitialized = true;
if (mIsWriteScheduled) {
// A write was scheduled while waiting for FD. We need to run/dispatch a
// task to service the request.
- mThread->Dispatch(this, NS_DISPATCH_NORMAL);
+ nsCOMPtr<nsIRunnable> event = mozilla::NewRunnableMethod(
+ "FileBlockCache::SetCacheFile -> PerformBlockIOs",
+ this,
+ &FileBlockCache::PerformBlockIOs);
+ mThread->Dispatch(event.forget(), NS_DISPATCH_NORMAL);
}
return;
}
}
// We've been closed while waiting for the file descriptor.
// Close the file descriptor we've just received, if still there.
MutexAutoLock lock(mFileMutex);
if (mFD) {
@@ -212,17 +216,21 @@ void FileBlockCache::EnsureWriteSchedule
return;
}
mIsWriteScheduled = true;
if (!mInitialized) {
// We're still waiting on a file descriptor. When it arrives,
// the write will be scheduled.
return;
}
- mThread->Dispatch(this, NS_DISPATCH_NORMAL);
+ nsCOMPtr<nsIRunnable> event = mozilla::NewRunnableMethod(
+ "FileBlockCache::EnsureWriteScheduled -> PerformBlockIOs",
+ this,
+ &FileBlockCache::PerformBlockIOs);
+ mThread->Dispatch(event.forget(), NS_DISPATCH_NORMAL);
}
nsresult FileBlockCache::Seek(int64_t aOffset)
{
mFileMutex.AssertCurrentThreadOwns();
if (mFDCurrentPos != aOffset) {
MOZ_ASSERT(mFD);
@@ -290,36 +298,37 @@ nsresult FileBlockCache::MoveBlockInFile
buf,
BLOCK_SIZE,
bytesRead))) {
return NS_ERROR_FAILURE;
}
return WriteBlockToFile(aDestBlockIndex, buf);
}
-nsresult FileBlockCache::Run()
+void
+FileBlockCache::PerformBlockIOs()
{
NS_ASSERTION(!NS_IsMainThread(), "Don't call on main thread");
MutexAutoLock mon(mDataMutex);
NS_ASSERTION(!mChangeIndexList.empty(), "Only dispatch when there's work to do");
NS_ASSERTION(mIsWriteScheduled, "Should report write running or scheduled.");
LOG("Run() mFD=%p mIsOpen=%d", mFD, mIsOpen);
while (!mChangeIndexList.empty()) {
if (!mIsOpen) {
// We've been closed, abort, discarding unwritten changes.
mIsWriteScheduled = false;
- return NS_ERROR_FAILURE;
+ return;
}
if (mIsReading) {
// We're trying to read; postpone all writes. (Reader will resume writes.)
mIsWriteScheduled = false;
- return NS_OK;
+ return;
}
// Process each pending change. We pop the index out of the change
// list, but leave the BlockChange in mBlockChanges until the change
// is written to file. This is so that any read which happens while
// we drop mDataMutex to write will refer to the data's source in
// memory, rather than the not-yet up to date data written to file.
// This also ensures we will insert a new index into mChangeIndexList
@@ -334,17 +343,17 @@ nsresult FileBlockCache::Run()
"Change index list should only contain entries for blocks "
"with changes");
{
MutexAutoUnlock unlock(mDataMutex);
MutexAutoLock lock(mFileMutex);
if (!mFD) {
// We may be here if mFD has been reset because we're closing, so we
// don't care anymore about writes.
- return NS_OK;
+ return;
}
if (change->IsWrite()) {
WriteBlockToFile(blockIndex, change->mData.get());
} else if (change->IsMove()) {
MoveBlockInFile(change->mSourceBlockIndex, blockIndex);
}
}
mChangeIndexList.pop_front();
@@ -352,18 +361,16 @@ nsresult FileBlockCache::Run()
// mDataMutex, clear reference to the old change. Otherwise, the old
// reference has been cleared already.
if (mBlockChanges[blockIndex] == change) {
mBlockChanges[blockIndex] = nullptr;
}
}
mIsWriteScheduled = false;
-
- return NS_OK;
}
nsresult FileBlockCache::Read(int64_t aOffset,
uint8_t* aData,
int32_t aLength,
int32_t* aBytes)
{
MutexAutoLock mon(mDataMutex);
--- a/dom/media/FileBlockCache.h
+++ b/dom/media/FileBlockCache.h
@@ -47,18 +47,21 @@ namespace mozilla {
// When WriteBlock() or MoveBlock() are called, data about how to complete
// the block change is added to mBlockChanges, indexed by block index, and
// the block index is appended to the mChangeIndexList. This enables
// us to quickly tell if a block has been changed, and ensures we can perform
// the changes in the correct order. An event is dispatched to perform the
// changes listed in mBlockChanges to file. Read() checks mBlockChanges and
// determines the current data to return, reading from file or from
// mBlockChanges as necessary.
-class FileBlockCache : public Runnable {
+class FileBlockCache
+{
public:
+ NS_INLINE_DECL_THREADSAFE_REFCOUNTING(FileBlockCache)
+
enum {
BLOCK_SIZE = MediaCacheStream::BLOCK_SIZE
};
FileBlockCache();
protected:
~FileBlockCache();
@@ -68,19 +71,16 @@ public:
// Closes writer, shuts down thread.
void Close();
// Can be called on any thread. This defers to a non-main thread.
nsresult WriteBlock(uint32_t aBlockIndex,
Span<const uint8_t> aData1, Span<const uint8_t> aData2);
- // Performs block writes and block moves on its own thread.
- NS_IMETHOD Run() override;
-
// Synchronously reads data from file. May read from file or memory
// depending on whether written blocks have been flushed to file yet.
// Not recommended to be called from the main thread, as can cause jank.
nsresult Read(int64_t aOffset,
uint8_t* aData,
int32_t aLength,
int32_t* aBytes);
@@ -138,16 +138,19 @@ public:
private:
int64_t BlockIndexToOffset(int32_t aBlockIndex) {
return static_cast<int64_t>(aBlockIndex) * BLOCK_SIZE;
}
void SetCacheFile(PRFileDesc* aFD);
+ // Performs block writes and block moves on its own thread.
+ void PerformBlockIOs();
+
// Mutex which controls access to mFD and mFDCurrentPos. Don't hold
// mDataMutex while holding mFileMutex! mFileMutex must be owned
// while accessing any of the following data fields or methods.
Mutex mFileMutex;
// Moves a block already committed to file.
nsresult MoveBlockInFile(int32_t aSourceBlockIndex,
int32_t aDestBlockIndex);
// Seeks file pointer.