From 9b73cdfdae55681142207dcb80b01ca408534eab Mon Sep 17 00:00:00 2001 From: Timothy Nikkel Date: Tue, 26 Aug 2014 23:02:10 -0500 Subject: [PATCH] Bug 1051531. When requesting decode of an image and not asking for some synchronous decoding check is some bytes have been decoding before acquiring the lock in order to avoid waiting on the decoding thread. r=seth We also need to move the check for if there is work done and subsequent FinishedSomeDecoding call to before acquiring the lock so that we notify if there is work done to notify about. The pointer value of mDecodeRequest can only be changed on the main thread (and we are on the main thread). It's okay to read the request status without locking it, if the request status changes it shouldn't cause any problems since this FinishedSomeDecoding call is just an optimization. --- image/src/RasterImage.cpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/image/src/RasterImage.cpp b/image/src/RasterImage.cpp index edb5f7e7125f..d233884bac7f 100644 --- a/image/src/RasterImage.cpp +++ b/image/src/RasterImage.cpp @@ -2330,6 +2330,31 @@ RasterImage::RequestDecodeCore(RequestDecodeType aDecodeType) } } + // If the image is waiting for decode work to be notified, go ahead and do that. + if (mDecodeRequest && + mDecodeRequest->mRequestStatus == DecodeRequest::REQUEST_WORK_DONE && + aDecodeType == SYNCHRONOUS_NOTIFY) { + ReentrantMonitorAutoEnter lock(mDecodingMonitor); + nsresult rv = FinishedSomeDecoding(); + CONTAINER_ENSURE_SUCCESS(rv); + } + + // If we're fully decoded, we have nothing to do. We need this check after + // DecodeUntilSizeAvailable and FinishedSomeDecoding because they can result + // in us finishing an in-progress decode (or kicking off and finishing a + // synchronous decode if we're already waiting on a full decode). + if (mDecoded) { + return NS_OK; + } + + // If we've already got a full decoder running, and have already decoded + // some bytes, we have nothing to do if we haven't been asked to do some + // sync decoding + if (mDecoder && !mDecoder->IsSizeDecode() && mBytesDecoded && + aDecodeType != SYNCHRONOUS_NOTIFY_AND_SOME_DECODE) { + return NS_OK; + } + ReentrantMonitorAutoEnter lock(mDecodingMonitor); // If we don't have any bytes to flush to the decoder, we can't do anything. @@ -2338,6 +2363,9 @@ RasterImage::RequestDecodeCore(RequestDecodeType aDecodeType) if (mBytesDecoded > mSourceData.Length()) return NS_OK; + // After acquiring the lock we may have finished some more decoding, so + // we need to repeat the following three checks after getting the lock. + // If the image is waiting for decode work to be notified, go ahead and do that. if (mDecodeRequest && mDecodeRequest->mRequestStatus == DecodeRequest::REQUEST_WORK_DONE &&