[core] Dismiss actors from sprite loader
and get rid of `SpriteLoaderWorker`, use `scheduleAndReplyValue()` API instead.
This commit is contained in:
@@ -532,8 +532,6 @@ add_library(
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/sprite/sprite_loader.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/sprite/sprite_loader.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/sprite/sprite_loader_observer.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/sprite/sprite_loader_worker.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/sprite/sprite_loader_worker.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/sprite/sprite_parser.cpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/sprite/sprite_parser.hpp
|
||||
${PROJECT_SOURCE_DIR}/src/mbgl/storage/asset_file_source.hpp
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
#include <mbgl/actor/scheduler.hpp>
|
||||
#include <mbgl/sprite/sprite_loader.hpp>
|
||||
#include <mbgl/sprite/sprite_loader_observer.hpp>
|
||||
#include <mbgl/sprite/sprite_loader_worker.hpp>
|
||||
#include <mbgl/sprite/sprite_parser.hpp>
|
||||
#include <mbgl/storage/file_source.hpp>
|
||||
#include <mbgl/storage/resource.hpp>
|
||||
@@ -20,24 +19,15 @@ namespace mbgl {
|
||||
|
||||
static SpriteLoaderObserver nullObserver;
|
||||
|
||||
struct SpriteLoader::Loader {
|
||||
Loader(SpriteLoader& imageManager)
|
||||
: mailbox(std::make_shared<Mailbox>(*Scheduler::GetCurrent())),
|
||||
worker(Scheduler::GetBackground(), ActorRef<SpriteLoader>(imageManager, mailbox)) {
|
||||
}
|
||||
|
||||
struct SpriteLoader::Data {
|
||||
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<SpriteLoaderWorker> worker;
|
||||
};
|
||||
|
||||
SpriteLoader::SpriteLoader(float pixelRatio_)
|
||||
: pixelRatio(pixelRatio_)
|
||||
, observer(&nullObserver) {
|
||||
}
|
||||
: pixelRatio(pixelRatio_), observer(&nullObserver), threadPool(Scheduler::GetBackground()) {}
|
||||
|
||||
SpriteLoader::~SpriteLoader() = default;
|
||||
|
||||
@@ -48,56 +38,70 @@ void SpriteLoader::load(const std::string& url, FileSource& fileSource) {
|
||||
return;
|
||||
}
|
||||
|
||||
loader = std::make_unique<Loader>(*this);
|
||||
data = std::make_unique<Data>();
|
||||
|
||||
loader->jsonRequest = fileSource.request(Resource::spriteJSON(url, pixelRatio), [this](Response res) {
|
||||
data->jsonRequest = fileSource.request(Resource::spriteJSON(url, pixelRatio), [this](Response res) {
|
||||
if (res.error) {
|
||||
observer->onSpriteError(std::make_exception_ptr(std::runtime_error(res.error->message)));
|
||||
} else if (res.notModified) {
|
||||
return;
|
||||
} else if (res.noContent) {
|
||||
loader->json = std::make_shared<std::string>();
|
||||
data->json = std::make_shared<std::string>();
|
||||
emitSpriteLoadedIfComplete();
|
||||
} else {
|
||||
// Only trigger a sprite loaded event we got new data.
|
||||
assert(loader->json != res.data);
|
||||
loader->json = std::move(res.data);
|
||||
assert(data->json != res.data);
|
||||
data->json = std::move(res.data);
|
||||
emitSpriteLoadedIfComplete();
|
||||
}
|
||||
});
|
||||
|
||||
loader->spriteRequest = fileSource.request(Resource::spriteImage(url, pixelRatio), [this](Response res) {
|
||||
data->spriteRequest = fileSource.request(Resource::spriteImage(url, pixelRatio), [this](Response res) {
|
||||
if (res.error) {
|
||||
observer->onSpriteError(std::make_exception_ptr(std::runtime_error(res.error->message)));
|
||||
} else if (res.notModified) {
|
||||
return;
|
||||
} else if (res.noContent) {
|
||||
loader->image = std::make_shared<std::string>();
|
||||
data->image = std::make_shared<std::string>();
|
||||
emitSpriteLoadedIfComplete();
|
||||
} else {
|
||||
assert(loader->image != res.data);
|
||||
loader->image = std::move(res.data);
|
||||
assert(data->image != res.data);
|
||||
data->image = std::move(res.data);
|
||||
emitSpriteLoadedIfComplete();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void SpriteLoader::emitSpriteLoadedIfComplete() {
|
||||
assert(loader);
|
||||
|
||||
if (!loader->image || !loader->json) {
|
||||
assert(data);
|
||||
if (!data->image || !data->json) {
|
||||
return;
|
||||
}
|
||||
|
||||
loader->worker.self().invoke(&SpriteLoaderWorker::parse, loader->image, loader->json);
|
||||
}
|
||||
struct ParseResult {
|
||||
std::vector<Immutable<style::Image::Impl>> images;
|
||||
std::exception_ptr error;
|
||||
};
|
||||
|
||||
void SpriteLoader::onParsed(std::vector<Immutable<style::Image::Impl>> result) {
|
||||
observer->onSpriteLoaded(std::move(result));
|
||||
}
|
||||
auto parseClosure = [image = data->image, json = data->json]() -> ParseResult {
|
||||
try {
|
||||
return {parseSprite(*image, *json), nullptr};
|
||||
} catch (...) {
|
||||
return {{}, std::current_exception()};
|
||||
}
|
||||
};
|
||||
|
||||
void SpriteLoader::onError(std::exception_ptr err) {
|
||||
observer->onSpriteError(err);
|
||||
auto resultClosure = [this, weak = weakFactory.makeWeakPtr()](ParseResult result) {
|
||||
if (!weak) return; // This instance has been deleted.
|
||||
|
||||
if (result.error) {
|
||||
observer->onSpriteError(result.error);
|
||||
return;
|
||||
}
|
||||
observer->onSpriteLoaded(std::move(result.images));
|
||||
};
|
||||
|
||||
threadPool->scheduleAndReplyValue(parseClosure, resultClosure);
|
||||
}
|
||||
|
||||
void SpriteLoader::setObserver(SpriteLoaderObserver* observer_) {
|
||||
|
||||
@@ -13,6 +13,7 @@ namespace mbgl {
|
||||
|
||||
class FileSource;
|
||||
class SpriteLoaderObserver;
|
||||
class Scheduler;
|
||||
|
||||
class SpriteLoader {
|
||||
public:
|
||||
@@ -28,15 +29,15 @@ private:
|
||||
|
||||
// Invoked by SpriteAtlasWorker
|
||||
friend class SpriteLoaderWorker;
|
||||
void onParsed(std::vector<Immutable<style::Image::Impl>>);
|
||||
void onError(std::exception_ptr);
|
||||
|
||||
const float pixelRatio;
|
||||
|
||||
struct Loader;
|
||||
std::unique_ptr<Loader> loader;
|
||||
struct Data;
|
||||
std::unique_ptr<Data> data;
|
||||
|
||||
SpriteLoaderObserver* observer = nullptr;
|
||||
std::shared_ptr<Scheduler> threadPool;
|
||||
mapbox::base::WeakPtrFactory<SpriteLoader> weakFactory{this};
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
#include <mbgl/sprite/sprite_loader_worker.hpp>
|
||||
#include <mbgl/sprite/sprite_loader.hpp>
|
||||
#include <mbgl/sprite/sprite_parser.hpp>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
SpriteLoaderWorker::SpriteLoaderWorker(ActorRef<SpriteLoaderWorker>, ActorRef<SpriteLoader> parent_)
|
||||
: parent(std::move(parent_)) {
|
||||
}
|
||||
|
||||
void SpriteLoaderWorker::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(&SpriteLoader::onParsed, parseSprite(*image, *json));
|
||||
} catch (...) {
|
||||
parent.invoke(&SpriteLoader::onError, std::current_exception());
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mbgl
|
||||
@@ -1,23 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <mbgl/actor/actor_ref.hpp>
|
||||
#include <mbgl/sprite/sprite_parser.hpp>
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
namespace mbgl {
|
||||
|
||||
class SpriteLoader;
|
||||
|
||||
class SpriteLoaderWorker {
|
||||
public:
|
||||
SpriteLoaderWorker(ActorRef<SpriteLoaderWorker>, ActorRef<SpriteLoader>);
|
||||
|
||||
void parse(std::shared_ptr<const std::string> image, std::shared_ptr<const std::string> json);
|
||||
|
||||
private:
|
||||
ActorRef<SpriteLoader> parent;
|
||||
};
|
||||
|
||||
} // namespace mbgl
|
||||
Reference in New Issue
Block a user