summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKonstantin Käfer <mail@kkaefer.com>2017-01-11 16:25:15 +0100
committerKonstantin Käfer <mail@kkaefer.com>2017-01-11 16:25:15 +0100
commita720cd6b6bf114a67a8136523a23ad86af2fc8b6 (patch)
treebc261971c1f3e8a2770515e467b4047a5acc73ac
parentd90998c7bb5f8d1548ad5394b7fb77be33f403fb (diff)
downloadqtlocation-mapboxgl-a720cd6b6bf114a67a8136523a23ad86af2fc8b6.tar.gz
[core] move default AssetFileSource to use actors
-rw-r--r--platform/default/asset_file_source.cpp127
-rw-r--r--platform/default/default_file_source.cpp4
-rw-r--r--src/mbgl/storage/asset_file_source.hpp8
-rw-r--r--test/storage/asset_file_source.test.cpp19
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();