diff options
author | Konstantin Käfer <mail@kkaefer.com> | 2017-01-11 16:25:15 +0100 |
---|---|---|
committer | Konstantin Käfer <mail@kkaefer.com> | 2017-01-11 16:25:15 +0100 |
commit | a720cd6b6bf114a67a8136523a23ad86af2fc8b6 (patch) | |
tree | bc261971c1f3e8a2770515e467b4047a5acc73ac | |
parent | d90998c7bb5f8d1548ad5394b7fb77be33f403fb (diff) | |
download | qtlocation-mapboxgl-a720cd6b6bf114a67a8136523a23ad86af2fc8b6.tar.gz |
[core] move default AssetFileSource to use actors
-rw-r--r-- | platform/default/asset_file_source.cpp | 127 | ||||
-rw-r--r-- | platform/default/default_file_source.cpp | 4 | ||||
-rw-r--r-- | src/mbgl/storage/asset_file_source.hpp | 8 | ||||
-rw-r--r-- | test/storage/asset_file_source.test.cpp | 19 |
4 files changed, 104 insertions, 54 deletions
diff --git a/platform/default/asset_file_source.cpp b/platform/default/asset_file_source.cpp index 1832818378..de7556b656 100644 --- a/platform/default/asset_file_source.cpp +++ b/platform/default/asset_file_source.cpp @@ -1,70 +1,115 @@ #include <mbgl/storage/asset_file_source.hpp> #include <mbgl/storage/response.hpp> +#include <mbgl/util/io.hpp> #include <mbgl/util/string.hpp> -#include <mbgl/util/thread.hpp> #include <mbgl/util/url.hpp> #include <mbgl/util/util.hpp> -#include <mbgl/util/io.hpp> +#include <mbgl/util/run_loop.hpp> + +#include <mbgl/actor/actor.hpp> +#include <mbgl/actor/actor_ref.hpp> -#include <sys/types.h> #include <sys/stat.h> +#include <sys/types.h> #include <unistd.h> namespace mbgl { class AssetFileSource::Impl { public: - Impl(std::string root_) - : root(std::move(root_)) { - } + Impl(Scheduler&, const std::string& root); - void request(const std::string& url, FileSource::Callback callback) { - std::string path; + class Request; + std::unique_ptr<Request> readFile(const Resource&, Callback); + void respond(std::weak_ptr<Callback>, Response); - if (url.size() <= 8 || url[8] == '/') { - // This is an empty or absolute path. - path = mbgl::util::percentDecode(url.substr(8)); - } else { - // This is a relative path. Prefix with the application root. - path = root + "/" + mbgl::util::percentDecode(url.substr(8)); - } +private: + std::shared_ptr<Mailbox> mailbox{ std::make_shared<Mailbox>(*util::RunLoop::Get()) }; + class Worker { + public: + Worker(ActorRef<Worker>, ActorRef<Impl>, std::string root); - Response response; - - struct stat buf; - int result = stat(path.c_str(), &buf); - - if (result == 0 && S_ISDIR(buf.st_mode)) { - response.error = std::make_unique<Response::Error>(Response::Error::Reason::NotFound); - } else if (result == -1 && errno == ENOENT) { - response.error = std::make_unique<Response::Error>(Response::Error::Reason::NotFound); - } else { - try { - response.data = std::make_shared<std::string>(util::read_file(path)); - } catch (...) { - response.error = std::make_unique<Response::Error>( - Response::Error::Reason::Other, - util::toString(std::current_exception())); - } - } + void readFile(const std::string& url, std::weak_ptr<Callback>); + + private: + ActorRef<Impl> impl; + const std::string root; + }; + Actor<Worker> worker; +}; - callback(response); +class AssetFileSource::Impl::Request : public AsyncRequest { +public: + Request(std::shared_ptr<Callback> callback_) : callback(std::move(callback_)) { } private: - std::string root; + std::shared_ptr<Callback> callback; }; -AssetFileSource::AssetFileSource(const std::string& root) - : thread(std::make_unique<util::Thread<Impl>>( - util::ThreadContext{"AssetFileSource", util::ThreadPriority::Low}, - root)) { +AssetFileSource::Impl::Worker::Worker(ActorRef<Worker>, ActorRef<Impl> impl_, std::string root_) + : impl(std::move(impl_)), root(std::move(root_)) { +} + +void AssetFileSource::Impl::Worker::readFile(const std::string& url, + std::weak_ptr<Callback> callback) { + std::string path; + + if (url.size() <= 8 || url[8] == '/') { + // This is an empty or absolute path. + path = mbgl::util::percentDecode(url.substr(8)); + } else { + // This is a relative path. Prefix with the application root. + path = root + "/" + mbgl::util::percentDecode(url.substr(8)); + } + + Response response; + + struct stat buf; + int result = stat(path.c_str(), &buf); + + if (result == 0 && S_ISDIR(buf.st_mode)) { + response.error = std::make_unique<Response::Error>(Response::Error::Reason::NotFound); + } else if (result == -1 && errno == ENOENT) { + response.error = std::make_unique<Response::Error>(Response::Error::Reason::NotFound); + } else { + try { + response.data = std::make_shared<std::string>(util::read_file(path)); + } catch (...) { + response.error = std::make_unique<Response::Error>( + Response::Error::Reason::Other, util::toString(std::current_exception())); + } + } + + impl.invoke(&Impl::respond, callback, response); +} + +AssetFileSource::Impl::Impl(Scheduler& scheduler, const std::string& root) + : worker(scheduler, ActorRef<Impl>(*this, mailbox), root) { +} + +std::unique_ptr<AssetFileSource::Impl::Request> +AssetFileSource::Impl::readFile(const Resource& resource, Callback callback) { + auto cb = std::make_shared<Callback>(std::move(callback)); + worker.invoke(&Worker::readFile, resource.url, cb); + return std::make_unique<Request>(std::move(cb)); +} + +void AssetFileSource::Impl::respond(std::weak_ptr<Callback> callback, Response response) { + if (auto locked = callback.lock()) { + (*locked)(response); + } +} + +AssetFileSource::AssetFileSource(Scheduler& scheduler, const std::string& root) + : impl(std::make_unique<Impl>(scheduler, root)) { } AssetFileSource::~AssetFileSource() = default; -std::unique_ptr<AsyncRequest> AssetFileSource::request(const Resource& resource, Callback callback) { - return thread->invokeWithCallback(&Impl::request, resource.url, callback); +std::unique_ptr<AsyncRequest> AssetFileSource::request(const Resource& resource, + Callback callback) { + return impl->readFile(resource, std::move(callback)); } } // namespace mbgl diff --git a/platform/default/default_file_source.cpp b/platform/default/default_file_source.cpp index 80ddb23050..03a75c5f7e 100644 --- a/platform/default/default_file_source.cpp +++ b/platform/default/default_file_source.cpp @@ -160,13 +160,13 @@ private: std::unordered_map<int64_t, std::unique_ptr<OfflineDownload>> downloads; }; -DefaultFileSource::DefaultFileSource(Scheduler&, +DefaultFileSource::DefaultFileSource(Scheduler& scheduler, const std::string& cachePath, const std::string& assetRoot, uint64_t maximumCacheSize) : thread(std::make_unique<util::Thread<Impl>>(util::ThreadContext{"DefaultFileSource", util::ThreadPriority::Low}, cachePath, maximumCacheSize)), - assetFileSource(std::make_unique<AssetFileSource>(assetRoot)), + assetFileSource(std::make_unique<AssetFileSource>(scheduler, assetRoot)), localFileSource(std::make_unique<LocalFileSource>()) { } diff --git a/src/mbgl/storage/asset_file_source.hpp b/src/mbgl/storage/asset_file_source.hpp index 71e5bbdab3..b3f861fb27 100644 --- a/src/mbgl/storage/asset_file_source.hpp +++ b/src/mbgl/storage/asset_file_source.hpp @@ -4,20 +4,18 @@ namespace mbgl { -namespace util { -template <typename T> class Thread; -} // namespace util +class Scheduler; class AssetFileSource : public FileSource { public: - AssetFileSource(const std::string& assetRoot); + AssetFileSource(Scheduler&, const std::string& assetRoot); ~AssetFileSource() override; std::unique_ptr<AsyncRequest> request(const Resource&, Callback) override; private: class Impl; - std::unique_ptr<util::Thread<Impl>> thread; + const std::unique_ptr<Impl> impl; }; } // namespace mbgl diff --git a/test/storage/asset_file_source.test.cpp b/test/storage/asset_file_source.test.cpp index 7e634fc68e..24a8a71f3d 100644 --- a/test/storage/asset_file_source.test.cpp +++ b/test/storage/asset_file_source.test.cpp @@ -2,6 +2,7 @@ #include <mbgl/util/platform.hpp> #include <mbgl/util/chrono.hpp> #include <mbgl/util/run_loop.hpp> +#include <mbgl/util/default_thread_pool.hpp> #include <mbgl/util/thread.hpp> #include <gtest/gtest.h> @@ -24,7 +25,8 @@ using namespace mbgl; TEST(AssetFileSource, Load) { util::RunLoop loop; - AssetFileSource fs(getFileSourceRoot()); + ThreadPool threadPool{ 1, { "Worker" } }; + AssetFileSource fs(threadPool, getFileSourceRoot()); // iOS seems to run out of file descriptors... #if TARGET_OS_IPHONE || __ANDROID__ @@ -91,7 +93,8 @@ TEST(AssetFileSource, Load) { TEST(AssetFileSource, EmptyFile) { util::RunLoop loop; - AssetFileSource fs(getFileSourceRoot()); + ThreadPool threadPool{ 1, { "Worker" } }; + AssetFileSource fs(threadPool, getFileSourceRoot()); std::unique_ptr<AsyncRequest> req = fs.request({ Resource::Unknown, "asset://empty" }, [&](Response res) { req.reset(); @@ -107,7 +110,8 @@ TEST(AssetFileSource, EmptyFile) { TEST(AssetFileSource, NonEmptyFile) { util::RunLoop loop; - AssetFileSource fs(getFileSourceRoot()); + ThreadPool threadPool{ 1, { "Worker" } }; + AssetFileSource fs(threadPool, getFileSourceRoot()); std::unique_ptr<AsyncRequest> req = fs.request({ Resource::Unknown, "asset://nonempty" }, [&](Response res) { req.reset(); @@ -123,7 +127,8 @@ TEST(AssetFileSource, NonEmptyFile) { TEST(AssetFileSource, NonExistentFile) { util::RunLoop loop; - AssetFileSource fs(getFileSourceRoot()); + ThreadPool threadPool{ 1, { "Worker" } }; + AssetFileSource fs(threadPool, getFileSourceRoot()); std::unique_ptr<AsyncRequest> req = fs.request({ Resource::Unknown, "asset://does_not_exist" }, [&](Response res) { req.reset(); @@ -140,7 +145,8 @@ TEST(AssetFileSource, NonExistentFile) { TEST(AssetFileSource, ReadDirectory) { util::RunLoop loop; - AssetFileSource fs(getFileSourceRoot()); + ThreadPool threadPool{ 1, { "Worker" } }; + AssetFileSource fs(threadPool, getFileSourceRoot()); std::unique_ptr<AsyncRequest> req = fs.request({ Resource::Unknown, "asset://directory" }, [&](Response res) { req.reset(); @@ -157,7 +163,8 @@ TEST(AssetFileSource, ReadDirectory) { TEST(AssetFileSource, URLEncoding) { util::RunLoop loop; - AssetFileSource fs(getFileSourceRoot()); + ThreadPool threadPool{ 1, { "Worker" } }; + AssetFileSource fs(threadPool, getFileSourceRoot()); std::unique_ptr<AsyncRequest> req = fs.request({ Resource::Unknown, "asset://%6eonempty" }, [&](Response res) { req.reset(); |