diff options
author | Thiago Marcos P. Santos <thiago@mapbox.com> | 2015-07-09 11:26:45 +0300 |
---|---|---|
committer | Thiago Marcos P. Santos <thiago@mapbox.com> | 2015-07-16 19:38:39 +0300 |
commit | a75cc8c06b8d931b3b85dd9ac6d852f84b06e5b2 (patch) | |
tree | d22f8b7ad6f93ccc5a2136ebbd0e797a5134d761 /src/mbgl/text/glyph_store.cpp | |
parent | c6e58515fcd83a49d8633dc769e1ad1e69074653 (diff) | |
download | qtlocation-mapboxgl-a75cc8c06b8d931b3b85dd9ac6d852f84b06e5b2.tar.gz |
Make Glyph requests from the Map Thread
Now the requests are bound to the Map Thread loop and
we can cancel it quickly when shutting down or changing
style.
Previously requests were made by the workers and we would
have to wait them to finish because workers are destroyed
before the GlyphStore. This was giving the impression that
the application was frozen (in fact it was, momentarily).
Diffstat (limited to 'src/mbgl/text/glyph_store.cpp')
-rw-r--r-- | src/mbgl/text/glyph_store.cpp | 102 |
1 files changed, 52 insertions, 50 deletions
diff --git a/src/mbgl/text/glyph_store.cpp b/src/mbgl/text/glyph_store.cpp index 0f507deb44..17c1524a88 100644 --- a/src/mbgl/text/glyph_store.cpp +++ b/src/mbgl/text/glyph_store.cpp @@ -1,95 +1,98 @@ #include <mbgl/text/glyph_store.hpp> -#include <mbgl/text/glyph_pbf.hpp> -#include <mbgl/text/font_stack.hpp> +#include <mbgl/text/font_stack.hpp> +#include <mbgl/text/glyph_pbf.hpp> #include <mbgl/util/exception.hpp> -#include <mbgl/util/uv_detail.hpp> +#include <mbgl/util/thread_context.hpp> namespace mbgl { -GlyphStore::GlyphStore(uv_loop_t* loop) - : asyncEmitGlyphRangeLoaded(std::make_unique<uv::async>(loop, [this] { emitGlyphRangeLoaded(); })), - asyncEmitGlyphRangeLoadedingFailed(std::make_unique<uv::async>(loop, [this] { emitGlyphRangeLoadingFailed(); })), - observer(nullptr) { - asyncEmitGlyphRangeLoaded->unref(); - asyncEmitGlyphRangeLoadedingFailed->unref(); +GlyphStore::GlyphStore() { } GlyphStore::~GlyphStore() { - observer = nullptr; -} - -void GlyphStore::setURL(const std::string &url) { - glyphURL = url; } -bool GlyphStore::requestGlyphRangesIfNeeded(const std::string& fontStackName, - const std::set<GlyphRange>& glyphRanges) { - bool requestIsNeeded = false; - - if (glyphRanges.empty()) { - return requestIsNeeded; - } +void GlyphStore::requestGlyphRange(const std::string& fontStackName, const GlyphRange& range) { + assert(util::ThreadContext::currentlyOn(util::ThreadType::Map)); auto successCallback = [this, fontStackName](GlyphPBF* glyph) { - auto fontStack = createFontStack(fontStackName); try { - glyph->parse(**fontStack); - asyncEmitGlyphRangeLoaded->send(); + { + auto fontStack = createFontStack(fontStackName); + glyph->parse(**fontStack); + } + emitGlyphRangeLoaded(); } catch (const std::exception&) { - std::lock_guard<std::mutex> lock(errorMessageMutex); - errorMessage = "Failed to parse [" + glyph->getURL() + "]"; - asyncEmitGlyphRangeLoadedingFailed->send(); + std::string message = "Failed to parse [" + glyph->getURL() + "]"; + emitGlyphRangeLoadingFailed(message); } }; auto failureCallback = [this](const std::string& message) { - std::lock_guard<std::mutex> lock(errorMessageMutex); - errorMessage = message; - asyncEmitGlyphRangeLoadedingFailed->send(); + emitGlyphRangeLoadingFailed(message); }; std::lock_guard<std::mutex> lock(rangesMutex); auto& rangeSets = ranges[fontStackName]; + const auto& rangeSetsIt = rangeSets.find(range); + if (rangeSetsIt != rangeSets.end()) { + return; + } + + rangeSets.emplace(range, std::make_unique<GlyphPBF>(glyphURL, fontStackName, range, + successCallback, failureCallback)); +} + + +bool GlyphStore::hasGlyphRanges(const std::string& fontStackName, const std::set<GlyphRange>& glyphRanges) { + if (glyphRanges.empty()) { + return true; + } + + std::lock_guard<std::mutex> lock(rangesMutex); + const auto& rangeSets = ranges[fontStackName]; + + bool hasRanges = true; + for (const auto& range : glyphRanges) { - const auto& rangeSets_it = rangeSets.find(range); - if (rangeSets_it == rangeSets.end()) { - auto glyph = std::make_unique<GlyphPBF>(glyphURL, fontStackName, range, - successCallback, failureCallback); - rangeSets.emplace(range, std::move(glyph)); - requestIsNeeded = true; + const auto& rangeSetsIt = rangeSets.find(range); + if (rangeSetsIt == rangeSets.end()) { + // Post the request to the Map thread. + workQueue.push(std::bind(&GlyphStore::requestGlyphRange, this, fontStackName, range)); + hasRanges = false; continue; } - if (!rangeSets_it->second->isParsed()) { - requestIsNeeded = true; + if (!rangeSetsIt->second->isParsed()) { + hasRanges = false; } } - return requestIsNeeded; + return hasRanges; } -util::exclusive<FontStack> GlyphStore::createFontStack(const std::string &fontStack) { +util::exclusive<FontStack> GlyphStore::createFontStack(const std::string& fontStack) { auto lock = std::make_unique<std::lock_guard<std::mutex>>(stacksMutex); - auto stack_it = stacks.find(fontStack); - if (stack_it == stacks.end()) { - stack_it = stacks.emplace(fontStack, std::make_unique<FontStack>()).first; + auto it = stacks.find(fontStack); + if (it == stacks.end()) { + it = stacks.emplace(fontStack, std::make_unique<FontStack>()).first; } - return { stack_it->second.get(), std::move(lock) }; + return { it->second.get(), std::move(lock) }; } util::exclusive<FontStack> GlyphStore::getFontStack(const std::string &fontStack) { auto lock = std::make_unique<std::lock_guard<std::mutex>>(stacksMutex); - const auto& stack_it = stacks.find(fontStack); - if (stack_it == stacks.end()) { + const auto& it = stacks.find(fontStack); + if (it == stacks.end()) { return { nullptr, nullptr }; } - return { stack_it->second.get(), std::move(lock) }; + return { it->second.get(), std::move(lock) }; } void GlyphStore::setObserver(Observer* observer_) { @@ -102,13 +105,12 @@ void GlyphStore::emitGlyphRangeLoaded() { } } -void GlyphStore::emitGlyphRangeLoadingFailed() { +void GlyphStore::emitGlyphRangeLoadingFailed(const std::string& message) { if (!observer) { return; } - std::lock_guard<std::mutex> lock(errorMessageMutex); - auto error = std::make_exception_ptr(util::GlyphRangeLoadingException(errorMessage)); + auto error = std::make_exception_ptr(util::GlyphRangeLoadingException(message)); observer->onGlyphRangeLoadingFailed(error); } |