diff options
author | Mikhail Pozdnyakov <mikhail.pozdnyakov@mapbox.com> | 2019-10-24 17:05:01 +0300 |
---|---|---|
committer | Mikhail Pozdnyakov <mikhail.pozdnyakov@mapbox.com> | 2019-10-28 13:02:32 +0200 |
commit | aa36dc87fb5583425ab29b4a15407186c31c492f (patch) | |
tree | 82d1e9eafa9aba4eecaaf76f3966773acfd50785 /src/mbgl/renderer | |
parent | 6428d12a8d3de572973202016b9ee19df4b288ed (diff) | |
download | qtlocation-mapboxgl-aa36dc87fb5583425ab29b4a15407186c31c492f.tar.gz |
Revert "[core] Revert coalescing requests to the client for the same missing image"
This reverts commit 22132683797b5ea5cbe8622f77c01b399ad9c71e.
Diffstat (limited to 'src/mbgl/renderer')
-rw-r--r-- | src/mbgl/renderer/image_manager.cpp | 70 | ||||
-rw-r--r-- | src/mbgl/renderer/image_manager.hpp | 17 |
2 files changed, 56 insertions, 31 deletions
diff --git a/src/mbgl/renderer/image_manager.cpp b/src/mbgl/renderer/image_manager.cpp index cc3e29cc79..7b51fb9a2e 100644 --- a/src/mbgl/renderer/image_manager.cpp +++ b/src/mbgl/renderer/image_manager.cpp @@ -138,8 +138,9 @@ void ImageManager::removeRequestor(ImageRequestor& requestor) { void ImageManager::notifyIfMissingImageAdded() { for (auto it = missingImageRequestors.begin(); it != missingImageRequestors.end();) { - if (it->second.callbacks.empty()) { - notify(*it->first, it->second.pair); + ImageRequestor& requestor = *it->first; + if (!requestor.hasPendingRequests()) { + notify(requestor, it->second); it = missingImageRequestors.erase(it); } else { ++it; @@ -169,35 +170,56 @@ void ImageManager::reduceMemoryUseIfCacheSizeExceedsLimit() { } void ImageManager::checkMissingAndNotify(ImageRequestor& requestor, const ImageRequestPair& pair) { - std::vector<std::string> missingImages; - missingImages.reserve(pair.first.size()); + ImageDependencies missingDependencies; + for (const auto& dependency : pair.first) { if (images.find(dependency.first) == images.end()) { - missingImages.push_back(dependency.first); + missingDependencies.emplace(dependency); } } - if (!missingImages.empty()) { + if (!missingDependencies.empty()) { ImageRequestor* requestorPtr = &requestor; + assert(!missingImageRequestors.count(requestorPtr)); + missingImageRequestors.emplace(requestorPtr, pair); - auto emplaced = missingImageRequestors.emplace(requestorPtr, MissingImageRequestPair{pair, {}}); - assert(emplaced.second); - - for (const auto& missingImage : missingImages) { + for (const auto& dependency : missingDependencies) { + const std::string& missingImage = dependency.first; assert(observer != nullptr); - requestedImages[missingImage].emplace(&requestor); - auto callback = - std::make_unique<ActorCallback>(*Scheduler::GetCurrent(), [this, requestorPtr, missingImage] { - auto requestorIt = missingImageRequestors.find(requestorPtr); - if (requestorIt != missingImageRequestors.end()) { - assert(requestorIt->second.callbacks.find(missingImage) != requestorIt->second.callbacks.end()); - requestorIt->second.callbacks.erase(missingImage); - } - }); - - auto actorRef = callback->self(); - emplaced.first->second.callbacks.emplace(missingImage, std::move(callback)); - observer->onStyleImageMissing(missingImage, [actorRef] { actorRef.invoke(&Callback::operator()); }); + + auto existingRequestorsIt = requestedImages.find(missingImage); + if (existingRequestorsIt != requestedImages.end()) { // Already asked client about this image. + std::set<ImageRequestor*>& existingRequestors = existingRequestorsIt->second; + if (!existingRequestors.empty() && + (*existingRequestors.begin()) + ->hasPendingRequest(missingImage)) { // Still waiting for the client response for this image. + requestorPtr->addPendingRequest(missingImage); + existingRequestors.emplace(requestorPtr); + continue; + } + // Unlike icons, pattern changes are not caught + // with style-diff meaning that the existing request + // could be from the previous style and we cannot + // coalesce requests for them. + if (dependency.second != ImageType::Pattern) { + continue; + } + } + requestedImages[missingImage].emplace(requestorPtr); + requestor.addPendingRequest(missingImage); + + auto removePendingRequests = [this, missingImage] { + auto existingRequest = requestedImages.find(missingImage); + if (existingRequest == requestedImages.end()) { + return; + } + + for (auto* req : existingRequest->second) { + req->removePendingRequest(missingImage); + } + }; + observer->onStyleImageMissing(missingImage, + Scheduler::GetCurrent()->bindOnce(std::move(removePendingRequests))); } } else { // Associate requestor with an image that was provided by the client. @@ -227,7 +249,7 @@ void ImageManager::notify(ImageRequestor& requestor, const ImageRequestPair& pai } } - requestor.onImagesAvailable(iconMap, patternMap, std::move(versionMap), pair.second); + requestor.onImagesAvailable(std::move(iconMap), std::move(patternMap), std::move(versionMap), pair.second); } void ImageManager::dumpDebugLogs() const { diff --git a/src/mbgl/renderer/image_manager.hpp b/src/mbgl/renderer/image_manager.hpp index 9097418681..5ed6e237f0 100644 --- a/src/mbgl/renderer/image_manager.hpp +++ b/src/mbgl/renderer/image_manager.hpp @@ -58,13 +58,7 @@ private: bool loaded = false; std::map<ImageRequestor*, ImageRequestPair> requestors; - using Callback = std::function<void()>; - using ActorCallback = Actor<Callback>; - struct MissingImageRequestPair { - ImageRequestPair pair; - std::map<std::string, std::unique_ptr<ActorCallback>> callbacks; - }; - std::map<ImageRequestor*, MissingImageRequestPair> missingImageRequestors; + std::map<ImageRequestor*, ImageRequestPair> missingImageRequestors; std::map<std::string, std::set<ImageRequestor*>> requestedImages; std::size_t requestedImagesCacheSize = 0ul; ImageMap images; @@ -77,8 +71,17 @@ public: explicit ImageRequestor(ImageManager&); virtual ~ImageRequestor(); virtual void onImagesAvailable(ImageMap icons, ImageMap patterns, ImageVersionMap versionMap, uint64_t imageCorrelationID) = 0; + + void addPendingRequest(const std::string& imageId) { pendingRequests.insert(imageId); } + bool hasPendingRequest(const std::string& imageId) const { return pendingRequests.count(imageId); } + bool hasPendingRequests() const { return !pendingRequests.empty(); } + void removePendingRequest(const std::string& imageId) { pendingRequests.erase(imageId); } + private: ImageManager& imageManager; + + // Pending requests are image requests that are waiting to be dispatched to the client. + std::set<std::string> pendingRequests; }; } // namespace mbgl |