diff options
author | Konstantin Käfer <mail@kkaefer.com> | 2017-04-20 12:28:35 +0200 |
---|---|---|
committer | Konstantin Käfer <mail@kkaefer.com> | 2017-04-24 10:42:47 +0200 |
commit | 59055cf403cab60496fcc8e7cbf06874fa55bb8b (patch) | |
tree | 7e74c6ba3fa9c2cc1930811302e8b93b48ab1687 /src/mbgl/sprite | |
parent | 197f0ca6b418a27412bfcc7e891ab80949fd8833 (diff) | |
download | qtlocation-mapboxgl-59055cf403cab60496fcc8e7cbf06874fa55bb8b.tar.gz |
[core] Move Sprite parsing to thread pool
Diffstat (limited to 'src/mbgl/sprite')
-rw-r--r-- | src/mbgl/sprite/sprite_atlas.cpp | 42 | ||||
-rw-r--r-- | src/mbgl/sprite/sprite_atlas.hpp | 11 | ||||
-rw-r--r-- | src/mbgl/sprite/sprite_atlas_worker.cpp | 29 | ||||
-rw-r--r-- | src/mbgl/sprite/sprite_atlas_worker.hpp | 23 | ||||
-rw-r--r-- | src/mbgl/sprite/sprite_parser.cpp | 20 | ||||
-rw-r--r-- | src/mbgl/sprite/sprite_parser.hpp | 7 |
6 files changed, 97 insertions, 35 deletions
diff --git a/src/mbgl/sprite/sprite_atlas.cpp b/src/mbgl/sprite/sprite_atlas.cpp index bdccf289df..3b774b627a 100644 --- a/src/mbgl/sprite/sprite_atlas.cpp +++ b/src/mbgl/sprite/sprite_atlas.cpp @@ -1,4 +1,5 @@ #include <mbgl/sprite/sprite_atlas.hpp> +#include <mbgl/sprite/sprite_atlas_worker.hpp> #include <mbgl/sprite/sprite_atlas_observer.hpp> #include <mbgl/sprite/sprite_parser.hpp> #include <mbgl/gl/context.hpp> @@ -11,6 +12,8 @@ #include <mbgl/storage/file_source.hpp> #include <mbgl/storage/resource.hpp> #include <mbgl/storage/response.hpp> +#include <mbgl/util/run_loop.hpp> +#include <mbgl/actor/actor.hpp> #include <cassert> #include <cmath> @@ -21,10 +24,17 @@ namespace mbgl { static SpriteAtlasObserver nullObserver; struct SpriteAtlas::Loader { + Loader(Scheduler& scheduler, SpriteAtlas& spriteAtlas) + : mailbox(std::make_shared<Mailbox>(*util::RunLoop::Get())), + worker(scheduler, ActorRef<SpriteAtlas>(spriteAtlas, mailbox)) { + } + std::shared_ptr<const std::string> image; std::shared_ptr<const std::string> json; std::unique_ptr<AsyncRequest> jsonRequest; std::unique_ptr<AsyncRequest> spriteRequest; + std::shared_ptr<Mailbox> mailbox; + Actor<SpriteAtlasWorker> worker; }; SpriteAtlasElement::SpriteAtlasElement(Rect<uint16_t> rect_, @@ -56,14 +66,14 @@ SpriteAtlas::SpriteAtlas(Size size_, float pixelRatio_) SpriteAtlas::~SpriteAtlas() = default; -void SpriteAtlas::load(const std::string& url, FileSource& fileSource) { +void SpriteAtlas::load(const std::string& url, Scheduler& scheduler, FileSource& fileSource) { if (url.empty()) { // Treat a non-existent sprite as a successfully loaded empty sprite. - loaded = true; + markAsLoaded(); return; } - loader = std::make_unique<Loader>(); + loader = std::make_unique<Loader>(scheduler, *this); loader->jsonRequest = fileSource.request(Resource::spriteJSON(url, pixelRatio), [this](Response res) { if (res.error) { @@ -102,18 +112,22 @@ void SpriteAtlas::emitSpriteLoadedIfComplete() { return; } - auto result = parseSprite(*loader->image, *loader->json); - if (result.is<Sprites>()) { - loaded = true; - setSprites(result.get<Sprites>()); - observer->onSpriteLoaded(); - for (auto requestor : requestors) { - requestor->onIconsAvailable(this, buildIconMap()); - } - requestors.clear(); - } else { - observer->onSpriteError(result.get<std::exception_ptr>()); + loader->worker.invoke(&SpriteAtlasWorker::parse, loader->image, loader->json); + // TODO: delete the loader? +} + +void SpriteAtlas::onParsed(Sprites&& result) { + markAsLoaded(); + setSprites(result); + observer->onSpriteLoaded(); + for (auto requestor : requestors) { + requestor->onIconsAvailable(this, buildIconMap()); } + requestors.clear(); +} + +void SpriteAtlas::onError(std::exception_ptr err) { + observer->onSpriteError(err); } void SpriteAtlas::setObserver(SpriteAtlasObserver* observer_) { diff --git a/src/mbgl/sprite/sprite_atlas.hpp b/src/mbgl/sprite/sprite_atlas.hpp index 3c37f57708..21df25d67d 100644 --- a/src/mbgl/sprite/sprite_atlas.hpp +++ b/src/mbgl/sprite/sprite_atlas.hpp @@ -15,6 +15,7 @@ namespace mbgl { +class Scheduler; class FileSource; class SpriteAtlasObserver; @@ -56,7 +57,11 @@ public: SpriteAtlas(Size, float pixelRatio); ~SpriteAtlas(); - void load(const std::string& url, FileSource&); + void load(const std::string& url, Scheduler&, FileSource&); + + void markAsLoaded() { + loaded = true; + } bool isLoaded() const { return loaded; @@ -97,6 +102,10 @@ private: void _setSprite(const std::string&, const std::shared_ptr<const SpriteImage>& = nullptr); void emitSpriteLoadedIfComplete(); + // Invoked by SpriteAtlasWorker + friend class SpriteAtlasWorker; + void onParsed(Sprites&& result); + void onError(std::exception_ptr); const Size size; const float pixelRatio; diff --git a/src/mbgl/sprite/sprite_atlas_worker.cpp b/src/mbgl/sprite/sprite_atlas_worker.cpp new file mode 100644 index 0000000000..da507aabab --- /dev/null +++ b/src/mbgl/sprite/sprite_atlas_worker.cpp @@ -0,0 +1,29 @@ +#include <mbgl/sprite/sprite_atlas_worker.hpp> +#include <mbgl/sprite/sprite_atlas.hpp> +#include <mbgl/sprite/sprite_parser.hpp> + +namespace mbgl { + +SpriteAtlasWorker::SpriteAtlasWorker(ActorRef<SpriteAtlasWorker>, ActorRef<SpriteAtlas> parent_) + : parent(std::move(parent_)) { +} + +void SpriteAtlasWorker::parse(std::shared_ptr<const std::string> image, + std::shared_ptr<const std::string> json) { + try { + if (!image) { + // This shouldn't happen, since we always invoke it with a non-empty pointer. + throw std::runtime_error("missing sprite image"); + } + if (!json) { + // This shouldn't happen, since we always invoke it with a non-empty pointer. + throw std::runtime_error("missing sprite metadata"); + } + + parent.invoke(&SpriteAtlas::onParsed, parseSprite(*image, *json)); + } catch (...) { + parent.invoke(&SpriteAtlas::onError, std::current_exception()); + } +} + +} // namespace mbgl diff --git a/src/mbgl/sprite/sprite_atlas_worker.hpp b/src/mbgl/sprite/sprite_atlas_worker.hpp new file mode 100644 index 0000000000..70ca0d52e5 --- /dev/null +++ b/src/mbgl/sprite/sprite_atlas_worker.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include <mbgl/actor/actor_ref.hpp> +#include <mbgl/sprite/sprite_parser.hpp> + +#include <memory> +#include <string> + +namespace mbgl { + +class SpriteAtlas; + +class SpriteAtlasWorker { +public: + SpriteAtlasWorker(ActorRef<SpriteAtlasWorker>, ActorRef<SpriteAtlas>); + + void parse(std::shared_ptr<const std::string> image, std::shared_ptr<const std::string> json); + +private: + ActorRef<SpriteAtlas> parent; +}; + +} // namespace mbgl diff --git a/src/mbgl/sprite/sprite_parser.cpp b/src/mbgl/sprite/sprite_parser.cpp index 66b5ec0606..96a883b0dd 100644 --- a/src/mbgl/sprite/sprite_parser.cpp +++ b/src/mbgl/sprite/sprite_parser.cpp @@ -84,26 +84,19 @@ bool getBoolean(const JSValue& value, const char* name, const bool def = false) } // namespace -SpriteParseResult parseSprite(const std::string& image, const std::string& json) { - Sprites sprites; - PremultipliedImage raster; - - try { - raster = decodeImage(image); - } catch (...) { - return std::current_exception(); - } +Sprites parseSprite(const std::string& image, const std::string& json) { + const PremultipliedImage raster = decodeImage(image); JSDocument doc; doc.Parse<0>(json.c_str()); - if (doc.HasParseError()) { std::stringstream message; message << "Failed to parse JSON: " << rapidjson::GetParseError_En(doc.GetParseError()) << " at offset " << doc.GetErrorOffset(); - return std::make_exception_ptr(std::runtime_error(message.str())); + throw std::runtime_error(message.str()); } else if (!doc.IsObject()) { - return std::make_exception_ptr(std::runtime_error("Sprite JSON root must be an object")); + throw std::runtime_error("Sprite JSON root must be an object"); } else { + Sprites sprites; for (const auto& property : doc.GetObject()) { const std::string name = { property.name.GetString(), property.name.GetStringLength() }; const JSValue& value = property.value; @@ -122,9 +115,8 @@ SpriteParseResult parseSprite(const std::string& image, const std::string& json) } } } + return sprites; } - - return sprites; } } // namespace mbgl diff --git a/src/mbgl/sprite/sprite_parser.hpp b/src/mbgl/sprite/sprite_parser.hpp index 4a63d4858a..9e462f324e 100644 --- a/src/mbgl/sprite/sprite_parser.hpp +++ b/src/mbgl/sprite/sprite_parser.hpp @@ -26,12 +26,7 @@ SpriteImagePtr createSpriteImage(const PremultipliedImage&, using Sprites = std::map<std::string, SpriteImagePtr>; - -using SpriteParseResult = variant< - Sprites, // success - std::exception_ptr>; // error - // Parses an image and an associated JSON file and returns the sprite objects. -SpriteParseResult parseSprite(const std::string& image, const std::string& json); +Sprites parseSprite(const std::string& image, const std::string& json); } // namespace mbgl |