[core] Dismiss actors from sprite loader

and get rid of `SpriteLoaderWorker`, use `scheduleAndReplyValue()` API instead.
This commit is contained in:
Mikhail Pozdnyakov
2020-02-18 14:10:37 +02:00
parent 43c1aac7e8
commit 75f861fe47
5 changed files with 40 additions and 89 deletions

View File

@@ -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

View File

@@ -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_) {

View File

@@ -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

View File

@@ -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

View File

@@ -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