partial fix for EXT-4352. fixed mutex deadlocks and turned on the multi-threaded texture fetching.
parent
ac59a7c130
commit
68ea8e13ac
|
|
@ -1679,7 +1679,7 @@ bool LLAppViewer::initThreads()
|
|||
// Image decoding
|
||||
LLAppViewer::sImageDecodeThread = new LLImageDecodeThread(enable_threads && true);
|
||||
LLAppViewer::sTextureCache = new LLTextureCache(enable_threads && true);
|
||||
LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(), sImageDecodeThread, enable_threads && false);
|
||||
LLAppViewer::sTextureFetch = new LLTextureFetch(LLAppViewer::getTextureCache(), sImageDecodeThread, enable_threads && true);
|
||||
LLImage::initClass();
|
||||
|
||||
if (LLFastTimer::sLog || LLFastTimer::sMetricLog)
|
||||
|
|
|
|||
|
|
@ -73,13 +73,11 @@ private:
|
|||
}
|
||||
virtual void completed(bool success)
|
||||
{
|
||||
mFetcher->lockQueue();
|
||||
LLTextureFetchWorker* worker = mFetcher->getWorker(mID);
|
||||
if (worker)
|
||||
{
|
||||
worker->callbackCacheRead(success, mFormattedImage, mImageSize, mImageLocal);
|
||||
}
|
||||
mFetcher->unlockQueue();
|
||||
}
|
||||
private:
|
||||
LLTextureFetch* mFetcher;
|
||||
|
|
@ -95,13 +93,11 @@ private:
|
|||
}
|
||||
virtual void completed(bool success)
|
||||
{
|
||||
mFetcher->lockQueue();
|
||||
LLTextureFetchWorker* worker = mFetcher->getWorker(mID);
|
||||
if (worker)
|
||||
{
|
||||
worker->callbackCacheWrite(success);
|
||||
}
|
||||
mFetcher->unlockQueue();
|
||||
}
|
||||
private:
|
||||
LLTextureFetch* mFetcher;
|
||||
|
|
@ -117,13 +113,11 @@ private:
|
|||
}
|
||||
virtual void completed(bool success, LLImageRaw* raw, LLImageRaw* aux)
|
||||
{
|
||||
mFetcher->lockQueue();
|
||||
LLTextureFetchWorker* worker = mFetcher->getWorker(mID);
|
||||
if (worker)
|
||||
{
|
||||
worker->callbackDecoded(success, raw, aux);
|
||||
}
|
||||
mFetcher->unlockQueue();
|
||||
}
|
||||
private:
|
||||
LLTextureFetch* mFetcher;
|
||||
|
|
@ -166,6 +160,8 @@ public:
|
|||
|
||||
void setGetStatus(U32 status, const std::string& reason)
|
||||
{
|
||||
LLMutexLock lock(&mWorkMutex);
|
||||
|
||||
mGetStatus = status;
|
||||
mGetReason = reason;
|
||||
}
|
||||
|
|
@ -307,7 +303,6 @@ public:
|
|||
}
|
||||
|
||||
lldebugs << "HTTP COMPLETE: " << mID << llendl;
|
||||
mFetcher->lockQueue();
|
||||
LLTextureFetchWorker* worker = mFetcher->getWorker(mID);
|
||||
if (worker)
|
||||
{
|
||||
|
|
@ -339,7 +334,6 @@ public:
|
|||
mFetcher->removeFromHTTPQueue(mID);
|
||||
llwarns << "Worker not found: " << mID << llendl;
|
||||
}
|
||||
mFetcher->unlockQueue();
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -1440,12 +1434,9 @@ bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, con
|
|||
return false;
|
||||
}
|
||||
|
||||
LLTextureFetchWorker* worker = NULL;
|
||||
LLMutexLock lock(&mQueueMutex);
|
||||
map_t::iterator iter = mRequestMap.find(id);
|
||||
if (iter != mRequestMap.end())
|
||||
LLTextureFetchWorker* worker = getWorker(id) ;
|
||||
if (worker)
|
||||
{
|
||||
worker = iter->second;
|
||||
if (worker->mHost != host)
|
||||
{
|
||||
llwarns << "LLTextureFetch::createRequest " << id << " called with multiple hosts: "
|
||||
|
|
@ -1494,41 +1485,48 @@ bool LLTextureFetch::createRequest(const std::string& url, const LLUUID& id, con
|
|||
return false; // need to wait for previous aborted request to complete
|
||||
}
|
||||
worker->lockWorkMutex();
|
||||
worker->mActiveCount++;
|
||||
worker->mNeedsAux = needs_aux;
|
||||
worker->setImagePriority(priority);
|
||||
worker->setDesiredDiscard(desired_discard, desired_size);
|
||||
worker->unlockWorkMutex();
|
||||
if (!worker->haveWork())
|
||||
{
|
||||
worker->mState = LLTextureFetchWorker::INIT;
|
||||
worker->unlockWorkMutex();
|
||||
|
||||
worker->addWork(0, LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority);
|
||||
}
|
||||
else
|
||||
{
|
||||
worker->unlockWorkMutex();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
worker = new LLTextureFetchWorker(this, url, id, host, priority, desired_discard, desired_size);
|
||||
lockQueue() ;
|
||||
mRequestMap[id] = worker;
|
||||
}
|
||||
unlockQueue() ;
|
||||
|
||||
worker->lockWorkMutex();
|
||||
worker->mActiveCount++;
|
||||
worker->mNeedsAux = needs_aux;
|
||||
worker->unlockWorkMutex();
|
||||
}
|
||||
|
||||
// llinfos << "REQUESTED: " << id << " Discard: " << desired_discard << llendl;
|
||||
return true;
|
||||
}
|
||||
|
||||
void LLTextureFetch::deleteRequest(const LLUUID& id, bool cancel)
|
||||
{
|
||||
LLMutexLock lock(&mQueueMutex);
|
||||
LLTextureFetchWorker* worker = getWorker(id);
|
||||
if (worker)
|
||||
{
|
||||
removeRequest(worker, cancel);
|
||||
}
|
||||
}
|
||||
|
||||
// protected
|
||||
void LLTextureFetch::addToNetworkQueue(LLTextureFetchWorker* worker)
|
||||
{
|
||||
lockQueue() ;
|
||||
bool in_request_map = (mRequestMap.find(worker->mID) != mRequestMap.end()) ;
|
||||
unlockQueue() ;
|
||||
|
||||
LLMutexLock lock(&mNetworkQueueMutex);
|
||||
if (mRequestMap.find(worker->mID) != mRequestMap.end())
|
||||
if (in_request_map)
|
||||
{
|
||||
// only add to the queue if in the request map
|
||||
// i.e. a delete has not been requested
|
||||
|
|
@ -1564,10 +1562,34 @@ void LLTextureFetch::removeFromHTTPQueue(const LLUUID& id)
|
|||
mHTTPTextureQueue.erase(id);
|
||||
}
|
||||
|
||||
// call lockQueue() first!
|
||||
void LLTextureFetch::deleteRequest(const LLUUID& id, bool cancel)
|
||||
{
|
||||
lockQueue() ;
|
||||
LLTextureFetchWorker* worker = getWorkerAfterLock(id);
|
||||
if (worker)
|
||||
{
|
||||
size_t erased_1 = mRequestMap.erase(worker->mID);
|
||||
unlockQueue() ;
|
||||
|
||||
llassert_always(erased_1 > 0) ;
|
||||
|
||||
removeFromNetworkQueue(worker, cancel);
|
||||
llassert_always(!(worker->getFlags(LLWorkerClass::WCF_DELETE_REQUESTED))) ;
|
||||
|
||||
worker->scheduleDelete();
|
||||
}
|
||||
else
|
||||
{
|
||||
unlockQueue() ;
|
||||
}
|
||||
}
|
||||
|
||||
void LLTextureFetch::removeRequest(LLTextureFetchWorker* worker, bool cancel)
|
||||
{
|
||||
lockQueue() ;
|
||||
size_t erased_1 = mRequestMap.erase(worker->mID);
|
||||
unlockQueue() ;
|
||||
|
||||
llassert_always(erased_1 > 0) ;
|
||||
removeFromNetworkQueue(worker, cancel);
|
||||
llassert_always(!(worker->getFlags(LLWorkerClass::WCF_DELETE_REQUESTED))) ;
|
||||
|
|
@ -1575,8 +1597,26 @@ void LLTextureFetch::removeRequest(LLTextureFetchWorker* worker, bool cancel)
|
|||
worker->scheduleDelete();
|
||||
}
|
||||
|
||||
S32 LLTextureFetch::getNumRequests()
|
||||
{
|
||||
lockQueue() ;
|
||||
S32 size = (S32)mRequestMap.size();
|
||||
unlockQueue() ;
|
||||
|
||||
return size ;
|
||||
}
|
||||
|
||||
S32 LLTextureFetch::getNumHTTPRequests()
|
||||
{
|
||||
mNetworkQueueMutex.lock() ;
|
||||
S32 size = (S32)mHTTPTextureQueue.size();
|
||||
mNetworkQueueMutex.unlock() ;
|
||||
|
||||
return size ;
|
||||
}
|
||||
|
||||
// call lockQueue() first!
|
||||
LLTextureFetchWorker* LLTextureFetch::getWorker(const LLUUID& id)
|
||||
LLTextureFetchWorker* LLTextureFetch::getWorkerAfterLock(const LLUUID& id)
|
||||
{
|
||||
LLTextureFetchWorker* res = NULL;
|
||||
map_t::iterator iter = mRequestMap.find(id);
|
||||
|
|
@ -1587,12 +1627,18 @@ LLTextureFetchWorker* LLTextureFetch::getWorker(const LLUUID& id)
|
|||
return res;
|
||||
}
|
||||
|
||||
LLTextureFetchWorker* LLTextureFetch::getWorker(const LLUUID& id)
|
||||
{
|
||||
LLMutexLock lock(&mQueueMutex) ;
|
||||
|
||||
return getWorkerAfterLock(id) ;
|
||||
}
|
||||
|
||||
|
||||
bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level,
|
||||
LLPointer<LLImageRaw>& raw, LLPointer<LLImageRaw>& aux)
|
||||
{
|
||||
bool res = false;
|
||||
LLMutexLock lock(&mQueueMutex);
|
||||
LLTextureFetchWorker* worker = getWorker(id);
|
||||
if (worker)
|
||||
{
|
||||
|
|
@ -1644,7 +1690,6 @@ bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level,
|
|||
bool LLTextureFetch::updateRequestPriority(const LLUUID& id, F32 priority)
|
||||
{
|
||||
bool res = false;
|
||||
LLMutexLock lock(&mQueueMutex);
|
||||
LLTextureFetchWorker* worker = getWorker(id);
|
||||
if (worker)
|
||||
{
|
||||
|
|
@ -1760,8 +1805,6 @@ void LLTextureFetch::sendRequestListToSimulators()
|
|||
}
|
||||
timer.reset();
|
||||
|
||||
LLMutexLock lock(&mQueueMutex);
|
||||
|
||||
// Send requests
|
||||
typedef std::set<LLTextureFetchWorker*,LLTextureFetchWorker::Compare> request_list_t;
|
||||
typedef std::map< LLHost, request_list_t > work_request_map_t;
|
||||
|
|
@ -1970,7 +2013,6 @@ bool LLTextureFetchWorker::insertPacket(S32 index, U8* data, S32 size)
|
|||
bool LLTextureFetch::receiveImageHeader(const LLHost& host, const LLUUID& id, U8 codec, U16 packets, U32 totalbytes,
|
||||
U16 data_size, U8* data)
|
||||
{
|
||||
LLMutexLock lock(&mQueueMutex);
|
||||
LLTextureFetchWorker* worker = getWorker(id);
|
||||
bool res = true;
|
||||
|
||||
|
|
@ -2003,7 +2045,9 @@ bool LLTextureFetch::receiveImageHeader(const LLHost& host, const LLUUID& id, U8
|
|||
if (!res)
|
||||
{
|
||||
++mBadPacketCount;
|
||||
mNetworkQueueMutex.lock() ;
|
||||
mCancelQueue[host].insert(id);
|
||||
mNetworkQueueMutex.unlock() ;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -2024,7 +2068,6 @@ bool LLTextureFetch::receiveImageHeader(const LLHost& host, const LLUUID& id, U8
|
|||
|
||||
bool LLTextureFetch::receiveImagePacket(const LLHost& host, const LLUUID& id, U16 packet_num, U16 data_size, U8* data)
|
||||
{
|
||||
LLMutexLock lock(&mQueueMutex);
|
||||
LLTextureFetchWorker* worker = getWorker(id);
|
||||
bool res = true;
|
||||
|
||||
|
|
@ -2048,7 +2091,9 @@ bool LLTextureFetch::receiveImagePacket(const LLHost& host, const LLUUID& id, U1
|
|||
if (!res)
|
||||
{
|
||||
++mBadPacketCount;
|
||||
mNetworkQueueMutex.lock() ;
|
||||
mCancelQueue[host].insert(id);
|
||||
mNetworkQueueMutex.unlock() ;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -2088,7 +2133,6 @@ BOOL LLTextureFetch::isFromLocalCache(const LLUUID& id)
|
|||
{
|
||||
BOOL from_cache = FALSE ;
|
||||
|
||||
LLMutexLock lock(&mQueueMutex);
|
||||
LLTextureFetchWorker* worker = getWorker(id);
|
||||
if (worker)
|
||||
{
|
||||
|
|
@ -2110,7 +2154,6 @@ S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& r
|
|||
F32 request_dtime = 999999.f;
|
||||
U32 fetch_priority = 0;
|
||||
|
||||
LLMutexLock lock(&mQueueMutex);
|
||||
LLTextureFetchWorker* worker = getWorker(id);
|
||||
if (worker && worker->haveWork())
|
||||
{
|
||||
|
|
|
|||
|
|
@ -77,13 +77,14 @@ public:
|
|||
S32 getFetchState(const LLUUID& id, F32& decode_progress_p, F32& requested_priority_p,
|
||||
U32& fetch_priority_p, F32& fetch_dtime_p, F32& request_dtime_p);
|
||||
void dump();
|
||||
S32 getNumRequests() { return mRequestMap.size(); }
|
||||
S32 getNumHTTPRequests() { return mHTTPTextureQueue.size(); }
|
||||
S32 getNumRequests() ;
|
||||
S32 getNumHTTPRequests() ;
|
||||
|
||||
// Public for access by callbacks
|
||||
void lockQueue() { mQueueMutex.lock(); }
|
||||
void unlockQueue() { mQueueMutex.unlock(); }
|
||||
LLTextureFetchWorker* getWorker(const LLUUID& id);
|
||||
LLTextureFetchWorker* getWorkerAfterLock(const LLUUID& id);
|
||||
|
||||
LLTextureInfo* getTextureInfo() { return &mTextureInfo; }
|
||||
|
||||
|
|
@ -92,7 +93,7 @@ protected:
|
|||
void removeFromNetworkQueue(LLTextureFetchWorker* worker, bool cancel);
|
||||
void addToHTTPQueue(const LLUUID& id);
|
||||
void removeFromHTTPQueue(const LLUUID& id);
|
||||
S32 getHTTPQueueSize() { return (S32)mHTTPTextureQueue.size(); }
|
||||
S32 getHTTPQueueSize() { return getNumHTTPRequests(); }
|
||||
void removeRequest(LLTextureFetchWorker* worker, bool cancel);
|
||||
// Called from worker thread (during doWork)
|
||||
void processCurlRequests();
|
||||
|
|
@ -111,8 +112,8 @@ public:
|
|||
S32 mBadPacketCount;
|
||||
|
||||
private:
|
||||
LLMutex mQueueMutex;
|
||||
LLMutex mNetworkQueueMutex;
|
||||
LLMutex mQueueMutex; //to protect mRequestMap only
|
||||
LLMutex mNetworkQueueMutex; //to protect mNetworkQueue, mHTTPTextureQueue and mCancelQueue.
|
||||
|
||||
LLTextureCache* mTextureCache;
|
||||
LLImageDecodeThread* mImageDecodeThread;
|
||||
|
|
|
|||
Loading…
Reference in New Issue