Bug 1436247 - Part 3. Process image decoding tasks in a more predictable order. r=tnikkel

Originally image decoding tasks were processed in a FILO ordering, due
to that being the most efficient way to use an nsTArray as a queue. This
patch changes the decoding pool to use an std::queue to promise FIFO
ordering (relative to the priority of the tasks). This will allow the
first images to be requested to be the first images displayed.
This commit is contained in:
Andrew Osmond
2018-02-13 06:43:31 -05:00
parent 71272991c2
commit a9a19c20a5

View File

@@ -6,6 +6,7 @@
#include "DecodePool.h" #include "DecodePool.h"
#include <algorithm> #include <algorithm>
#include <queue>
#include "mozilla/ClearOnShutdown.h" #include "mozilla/ClearOnShutdown.h"
#include "mozilla/DebugOnly.h" #include "mozilla/DebugOnly.h"
@@ -131,15 +132,15 @@ public:
} }
if (task->Priority() == TaskPriority::eHigh) { if (task->Priority() == TaskPriority::eHigh) {
mHighPriorityQueue.AppendElement(Move(task)); mHighPriorityQueue.push(Move(task));
} else { } else {
mLowPriorityQueue.AppendElement(Move(task)); mLowPriorityQueue.push(Move(task));
} }
// If there are pending tasks, create more workers if and only if we have // If there are pending tasks, create more workers if and only if we have
// not exceeded the capacity, and any previously created workers are ready. // not exceeded the capacity, and any previously created workers are ready.
if (mAvailableThreads) { if (mAvailableThreads) {
size_t pending = mHighPriorityQueue.Length() + mLowPriorityQueue.Length(); size_t pending = mHighPriorityQueue.size() + mLowPriorityQueue.size();
if (pending > mIdleThreads) { if (pending > mIdleThreads) {
CreateThread(); CreateThread();
} }
@@ -174,11 +175,11 @@ private:
PRIntervalTime timeout = mIdleTimeout; PRIntervalTime timeout = mIdleTimeout;
do { do {
if (!mHighPriorityQueue.IsEmpty()) { if (!mHighPriorityQueue.empty()) {
return PopWorkFromQueue(mHighPriorityQueue); return PopWorkFromQueue(mHighPriorityQueue);
} }
if (!mLowPriorityQueue.IsEmpty()) { if (!mLowPriorityQueue.empty()) {
return PopWorkFromQueue(mLowPriorityQueue); return PopWorkFromQueue(mLowPriorityQueue);
} }
@@ -223,13 +224,12 @@ private:
bool CreateThread(); bool CreateThread();
Work PopWorkFromQueue(nsTArray<RefPtr<IDecodingTask>>& aQueue) Work PopWorkFromQueue(std::queue<RefPtr<IDecodingTask>>& aQueue)
{ {
Work work; Work work;
work.mType = Work::Type::TASK; work.mType = Work::Type::TASK;
work.mTask = aQueue.LastElement().forget(); work.mTask = aQueue.front().forget();
aQueue.RemoveElementAt(aQueue.Length() - 1); aQueue.pop();
return work; return work;
} }
@@ -244,8 +244,8 @@ private:
// mMonitor guards everything below. // mMonitor guards everything below.
Monitor mMonitor; Monitor mMonitor;
nsTArray<RefPtr<IDecodingTask>> mHighPriorityQueue; std::queue<RefPtr<IDecodingTask>> mHighPriorityQueue;
nsTArray<RefPtr<IDecodingTask>> mLowPriorityQueue; std::queue<RefPtr<IDecodingTask>> mLowPriorityQueue;
nsTArray<nsCOMPtr<nsIThread>> mThreads; nsTArray<nsCOMPtr<nsIThread>> mThreads;
PRIntervalTime mIdleTimeout; PRIntervalTime mIdleTimeout;
uint8_t mMaxIdleThreads; // Maximum number of workers when idle. uint8_t mMaxIdleThreads; // Maximum number of workers when idle.