From 22d62720e839e9044385133059e09e369ac04162 Mon Sep 17 00:00:00 2001
From: Rye Mutt <rye@alchemyviewer.org>
Date: Mon, 30 Jan 2023 02:36:43 -0500
Subject: [PATCH] Tweak texture decode thread behavior to not choke

---
 indra/llimage/llimageworker.cpp | 48 ++++++++++++++++++---------------
 1 file changed, 27 insertions(+), 21 deletions(-)

diff --git a/indra/llimage/llimageworker.cpp b/indra/llimage/llimageworker.cpp
index b84d40df31b..0f9e505e75b 100644
--- a/indra/llimage/llimageworker.cpp
+++ b/indra/llimage/llimageworker.cpp
@@ -35,7 +35,8 @@ std::atomic< U32 > sImageThreads = 0;
 class PoolWorkerThread final : public LLThread
 {
 public:
-	PoolWorkerThread(std::string name) : LLThread(name), mRequestQueue(256)
+	PoolWorkerThread(std::string name) : LLThread(name),
+		mCurrentRequest(NULL)
 	{
 	}
 
@@ -43,36 +44,40 @@ class PoolWorkerThread final : public LLThread
 	{
 		while (!isQuitting())
 		{
-            checkPause();
-
-			LLImageDecodeThread::ImageRequest* req  = nullptr;
-            while (!isQuitting() && mRequestQueue.tryPop(req))
-            {
-                if (req)
-                {
-                    req->processRequestIntern();
-                }
-            }
+			auto *pReq = mCurrentRequest.exchange(nullptr);
+
+			if (pReq)
+				pReq->processRequestIntern();
+			checkPause();
 		}
 	}
+	bool isBusy()
+	{
+		auto *pReq = mCurrentRequest.load();
+		if (!pReq)
+			return false;
+
+		auto status = pReq->getStatus();
+
+		return status  == LLQueuedThread::STATUS_QUEUED || status == LLQueuedThread::STATUS_INPROGRESS;
+	}
 
 	bool runCondition()
-    {
-        return mRequestQueue.size() > 0;
+	{
+		return mCurrentRequest != NULL;
 	}
 
 	bool setRequest(LLImageDecodeThread::ImageRequest* req)
 	{
-        bool bSuccess = mRequestQueue.tryPush(req);
-		if(bSuccess)
-		{
-		    wake();
-		}
+		LLImageDecodeThread::ImageRequest* pOld{ nullptr };
+		bool bSuccess = mCurrentRequest.compare_exchange_strong(pOld, req);
+		wake();
+
 		return bSuccess;
 	}
 
 private:
-	LLThreadSafeQueue<LLImageDecodeThread::ImageRequest*> mRequestQueue;
+	std::atomic<LLImageDecodeThread::ImageRequest*> mCurrentRequest;
 };
 
 //----------------------------------------------------------------------------
@@ -344,13 +349,14 @@ bool LLImageDecodeThread::ImageRequest::tut_isOK()
 
 bool LLImageDecodeThread::enqueRequest(ImageRequest * req)
 {
+	for(size_t num_tries = 0, pool_size = mThreadPool.size(); num_tries < pool_size; ++num_tries)
     {
-        if (mLastPoolAllocation >= mThreadPool.size())
+        if (mLastPoolAllocation >= pool_size)
         {
             mLastPoolAllocation = 0;
         }
         auto& thread = mThreadPool[mLastPoolAllocation++];
-        if (thread->setRequest(req))
+        if (!thread->isBusy() && thread->setRequest(req))
         {
             return true;
         }
-- 
GitLab