diff options
Diffstat (limited to 'indra/newview/lllandmarklist.cpp')
-rw-r--r-- | indra/newview/lllandmarklist.cpp | 53 |
1 files changed, 52 insertions, 1 deletions
diff --git a/indra/newview/lllandmarklist.cpp b/indra/newview/lllandmarklist.cpp index c58540914e..543d2a087f 100644 --- a/indra/newview/lllandmarklist.cpp +++ b/indra/newview/lllandmarklist.cpp @@ -39,6 +39,11 @@ // Globals LLLandmarkList gLandmarkList; +// number is mostly arbitrary, but it should be below DEFAULT_QUEUE_SIZE pool size, +// which is 4096, to not overfill the pool if user has more than 4K of landmarks +// and it should leave some space for other potential simultaneous asset request +const S32 MAX_SIMULTANEOUS_REQUESTS = 512; + //////////////////////////////////////////////////////////////////////////// // LLLandmarkList @@ -69,6 +74,11 @@ LLLandmark* LLLandmarkList::getAsset(const LLUUID& asset_uuid, loaded_callback_t { return NULL; } + if ( mWaitList.find(asset_uuid) != mWaitList.end() ) + { + // Landmark is sheduled for download, but not requested yet + return NULL; + } landmark_requested_list_t::iterator iter = mRequestedList.find(asset_uuid); if (iter != mRequestedList.end()) @@ -86,11 +96,24 @@ LLLandmark* LLLandmarkList::getAsset(const LLUUID& asset_uuid, loaded_callback_t mLoadedCallbackMap.insert(vt); } + if (mRequestedList.size() > MAX_SIMULTANEOUS_REQUESTS) + { + // Workarounds for corutines pending list size limit: + // Postpone download till queue is emptier. + // Coroutines have own built in 'pending' list, but unfortunately + // it is too small compared to potential amount of landmarks + // or assets. + mWaitList.insert(asset_uuid); + return NULL; + } + + mRequestedList[asset_uuid] = gFrameTimeSeconds; + + // Note that getAssetData can callback immediately and cleans mRequestedList gAssetStorage->getAssetData(asset_uuid, LLAssetType::AT_LANDMARK, LLLandmarkList::processGetAssetReply, NULL); - mRequestedList[asset_uuid] = gFrameTimeSeconds; } return NULL; } @@ -155,8 +178,36 @@ void LLLandmarkList::processGetAssetReply( } gLandmarkList.mBadList.insert(uuid); + gLandmarkList.mRequestedList.erase(uuid); //mBadList effectively blocks any load, so no point keeping id in requests + // todo: this should clean mLoadedCallbackMap! } + // getAssetData can fire callback immediately, causing + // a recursion which is suboptimal for very large wait list. + // 'scheduling' indicates that we are inside request and + // shouldn't be launching more requests. + static bool scheduling = false; + if (!scheduling && !gLandmarkList.mWaitList.empty()) + { + scheduling = true; + while (!gLandmarkList.mWaitList.empty() && gLandmarkList.mRequestedList.size() < MAX_SIMULTANEOUS_REQUESTS) + { + // start new download from wait list + landmark_uuid_list_t::iterator iter = gLandmarkList.mWaitList.begin(); + LLUUID asset_uuid = *iter; + gLandmarkList.mWaitList.erase(iter); + + // add to mRequestedList before calling getAssetData() + gLandmarkList.mRequestedList[asset_uuid] = gFrameTimeSeconds; + + // Note that getAssetData can callback immediately and cleans mRequestedList + gAssetStorage->getAssetData(asset_uuid, + LLAssetType::AT_LANDMARK, + LLLandmarkList::processGetAssetReply, + NULL); + } + scheduling = false; + } } BOOL LLLandmarkList::isAssetInLoadedCallbackMap(const LLUUID& asset_uuid) |