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:
@@ -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.
|
||||||
|
|||||||
Reference in New Issue
Block a user