[core] Move resource loader to dedicated thread with scheduler

This commit is contained in:
Alexander Shalamov
2020-01-22 17:16:34 +02:00
parent 4678b3d70c
commit 7bf4de9f39
2 changed files with 53 additions and 81 deletions

View File

@@ -6,59 +6,23 @@
#include <mbgl/storage/resource.hpp>
#include <mbgl/storage/resource_options.hpp>
#include <mbgl/util/stopwatch.hpp>
#include <mbgl/util/thread.hpp>
#include <cassert>
namespace mbgl {
class ResourceLoaderRequestor {
class MainResourceLoaderThread {
public:
explicit ResourceLoaderRequestor(MainResourceLoader::Impl& impl_);
void request(AsyncRequest*, Resource, ActorRef<FileSourceRequest>);
void cancel(AsyncRequest*);
void pause();
void resume();
private:
MainResourceLoader::Impl& impl;
};
class MainResourceLoader::Impl {
public:
Impl(std::shared_ptr<FileSource> assetFileSource_,
std::shared_ptr<FileSource> databaseFileSource_,
std::shared_ptr<FileSource> localFileSource_,
std::shared_ptr<FileSource> onlineFileSource_)
MainResourceLoaderThread(std::shared_ptr<FileSource> assetFileSource_,
std::shared_ptr<FileSource> databaseFileSource_,
std::shared_ptr<FileSource> localFileSource_,
std::shared_ptr<FileSource> onlineFileSource_)
: assetFileSource(std::move(assetFileSource_)),
databaseFileSource(std::move(databaseFileSource_)),
localFileSource(std::move(localFileSource_)),
onlineFileSource(std::move(onlineFileSource_)),
supportsCacheOnlyRequests_(bool(databaseFileSource)),
requestor(std::make_unique<Actor<ResourceLoaderRequestor>>(*Scheduler::GetCurrent(), *this)) {}
onlineFileSource(std::move(onlineFileSource_)) {}
std::unique_ptr<AsyncRequest> request(const Resource& resource, Callback callback) {
auto req = std::make_unique<FileSourceRequest>(std::move(callback));
req->onCancel([actorRef = requestor->self(), req = req.get()]() {
actorRef.invoke(&ResourceLoaderRequestor::cancel, req);
});
requestor->self().invoke(&ResourceLoaderRequestor::request, req.get(), resource, req->actor());
return std::move(req);
}
bool canRequest(const Resource& resource) const {
return (assetFileSource && assetFileSource->canRequest(resource)) ||
(localFileSource && localFileSource->canRequest(resource)) ||
(databaseFileSource && databaseFileSource->canRequest(resource)) ||
(onlineFileSource && onlineFileSource->canRequest(resource));
}
bool supportsCacheOnlyRequests() const { return supportsCacheOnlyRequests_; }
void pause() { requestor->self().invoke(&ResourceLoaderRequestor::pause); }
void resume() { requestor->self().invoke(&ResourceLoaderRequestor::resume); }
private:
void request(AsyncRequest* req, Resource resource, ActorRef<FileSourceRequest> ref) {
auto callback = [ref](const Response& res) { ref.invoke(&FileSourceRequest::setResponse, res); };
@@ -142,56 +106,65 @@ private:
}
}
void pauseInternal() {
if (assetFileSource) assetFileSource->pause();
if (databaseFileSource) databaseFileSource->pause();
if (localFileSource) localFileSource->pause();
if (onlineFileSource) onlineFileSource->pause();
}
void resumeInternal() {
if (assetFileSource) assetFileSource->resume();
if (databaseFileSource) databaseFileSource->resume();
if (localFileSource) localFileSource->resume();
if (onlineFileSource) onlineFileSource->resume();
}
void cancel(AsyncRequest* req) {
assert(req);
tasks.erase(req);
}
private:
friend class ResourceLoaderRequestor;
const std::shared_ptr<FileSource> assetFileSource;
const std::shared_ptr<FileSource> databaseFileSource;
const std::shared_ptr<FileSource> localFileSource;
const std::shared_ptr<FileSource> onlineFileSource;
std::unordered_map<AsyncRequest*, std::unique_ptr<AsyncRequest>> tasks;
};
class MainResourceLoader::Impl {
public:
Impl(std::shared_ptr<FileSource> assetFileSource_,
std::shared_ptr<FileSource> databaseFileSource_,
std::shared_ptr<FileSource> localFileSource_,
std::shared_ptr<FileSource> onlineFileSource_)
: assetFileSource(std::move(assetFileSource_)),
databaseFileSource(std::move(databaseFileSource_)),
localFileSource(std::move(localFileSource_)),
onlineFileSource(std::move(onlineFileSource_)),
supportsCacheOnlyRequests_(bool(databaseFileSource)),
thread(std::make_unique<util::Thread<MainResourceLoaderThread>>(
"ResourceLoaderThread", assetFileSource, databaseFileSource, localFileSource, onlineFileSource)) {}
std::unique_ptr<AsyncRequest> request(const Resource& resource, Callback callback) {
auto req = std::make_unique<FileSourceRequest>(std::move(callback));
req->onCancel([actorRef = thread->actor(), req = req.get()]() {
actorRef.invoke(&MainResourceLoaderThread::cancel, req);
});
thread->actor().invoke(&MainResourceLoaderThread::request, req.get(), resource, req->actor());
return std::move(req);
}
bool canRequest(const Resource& resource) const {
return (assetFileSource && assetFileSource->canRequest(resource)) ||
(localFileSource && localFileSource->canRequest(resource)) ||
(databaseFileSource && databaseFileSource->canRequest(resource)) ||
(onlineFileSource && onlineFileSource->canRequest(resource));
}
bool supportsCacheOnlyRequests() const { return supportsCacheOnlyRequests_; }
void pause() { thread->pause(); }
void resume() { thread->resume(); }
private:
const std::shared_ptr<FileSource> assetFileSource;
const std::shared_ptr<FileSource> databaseFileSource;
const std::shared_ptr<FileSource> localFileSource;
const std::shared_ptr<FileSource> onlineFileSource;
const bool supportsCacheOnlyRequests_;
std::unique_ptr<Actor<ResourceLoaderRequestor>> requestor;
std::unordered_map<AsyncRequest*, std::unique_ptr<AsyncRequest>> tasks;
const std::unique_ptr<util::Thread<MainResourceLoaderThread>> thread;
};
ResourceLoaderRequestor::ResourceLoaderRequestor(MainResourceLoader::Impl& impl_) : impl(impl_) {}
void ResourceLoaderRequestor::request(AsyncRequest* req, Resource resource, ActorRef<FileSourceRequest> ref) {
assert(req);
impl.request(req, std::move(resource), std::move(ref));
}
void ResourceLoaderRequestor::cancel(AsyncRequest* req) {
assert(req);
impl.cancel(req);
}
void ResourceLoaderRequestor::pause() {
impl.pauseInternal();
}
void ResourceLoaderRequestor::resume() {
impl.resumeInternal();
}
MainResourceLoader::MainResourceLoader(const ResourceOptions& options)
: impl(std::make_unique<Impl>(FileSourceManager::get()->getFileSource(FileSourceType::Asset, options),
FileSourceManager::get()->getFileSource(FileSourceType::Database, options),

View File

@@ -19,7 +19,6 @@ public:
void resume() override;
private:
friend class ResourceLoaderRequestor;
class Impl;
const std::unique_ptr<Impl> impl;
};