summaryrefslogtreecommitdiff
path: root/src/mbgl/storage
diff options
context:
space:
mode:
authorKonstantin Käfer <mail@kkaefer.com>2015-03-04 12:32:14 +0100
committerKonstantin Käfer <mail@kkaefer.com>2015-03-06 08:21:47 -0800
commit9781785ab73e8394e8b92625cc4741952f47955d (patch)
tree1b9e6b86c1c9ca19bb1bf1c52bcd0e41410ced66 /src/mbgl/storage
parent8c0acecbe362be4a40638491b67ee5fe3d23a65e (diff)
downloadqtlocation-mapboxgl-9781785ab73e8394e8b92625cc4741952f47955d.tar.gz
scope Requests to an Environment object for easier cancelation
we are now scoping all file requests to an environment object. The FileSource implementation treats this as an opaque pointer, but allows canceling all Requests that are associated with that pointer. This is necessary to abort all file requests that originated from a particular Map object. Aborting a file request is different from canceling a file request: A canceled request doesn't have its callback called, while an aborted request will have its callback called with an error, indicating that the environment is going to be shut down.
Diffstat (limited to 'src/mbgl/storage')
-rw-r--r--src/mbgl/storage/default_file_source.cpp62
-rw-r--r--src/mbgl/storage/request.cpp4
2 files changed, 52 insertions, 14 deletions
diff --git a/src/mbgl/storage/default_file_source.cpp b/src/mbgl/storage/default_file_source.cpp
index c6b201b559..9f70ac9943 100644
--- a/src/mbgl/storage/default_file_source.cpp
+++ b/src/mbgl/storage/default_file_source.cpp
@@ -50,6 +50,10 @@ struct DefaultFileSource::ResultAction {
struct DefaultFileSource::StopAction {
};
+struct DefaultFileSource::AbortAction {
+ const Environment &env;
+};
+
DefaultFileSource::DefaultFileSource(FileCache *cache_, const std::string &root)
: assetRoot(root.empty() ? platform::assetRoot() : root),
@@ -105,8 +109,9 @@ SharedRequestBase *DefaultFileSource::find(const Resource &resource) {
return nullptr;
}
-Request *DefaultFileSource::request(const Resource &resource, uv_loop_t *l, Callback callback) {
- auto req = new Request(resource, l, std::move(callback));
+Request *DefaultFileSource::request(const Resource &resource, uv_loop_t *l, const Environment &env,
+ Callback callback) {
+ auto req = new Request(resource, l, env, std::move(callback));
// This function can be called from any thread. Make sure we're executing the actual call in the
// file source loop by sending it over the queue. It will be processed in processAction().
@@ -114,8 +119,9 @@ Request *DefaultFileSource::request(const Resource &resource, uv_loop_t *l, Call
return req;
}
-void DefaultFileSource::request(const Resource &resource, Callback callback) {
- auto req = new Request(resource, nullptr, std::move(callback));
+void DefaultFileSource::request(const Resource &resource, const Environment &env,
+ Callback callback) {
+ auto req = new Request(resource, nullptr, env, std::move(callback));
// This function can be called from any thread. Make sure we're executing the actual call in the
// file source loop by sending it over the queue. It will be processed in processAction().
@@ -130,6 +136,11 @@ void DefaultFileSource::cancel(Request *req) {
queue->send(RemoveRequestAction{ req });
}
+void DefaultFileSource::abort(const Environment &env) {
+ queue->send(AbortAction{ env });
+}
+
+
void DefaultFileSource::process(AddRequestAction &action) {
const Resource &resource = action.request->resource;
@@ -209,18 +220,45 @@ void DefaultFileSource::process(ResultAction &action) {
}
}
+// A stop action means the file source is about to be destructed. We need to cancel all requests
+// for all environments.
void DefaultFileSource::process(StopAction &) {
- // Cancel all remaining requests.
- for (auto it : pending) {
- it.second->unsubscribeAll();
- }
- pending.clear();
-
+ // There may not be any pending requests in this file source anymore. You must terminate all
+ // Map objects before deleting the FileSource.
+ assert(pending.empty());
assert(queue);
queue->stop();
queue = nullptr;
}
+// Aborts all requests that are part of the current environment.
+void DefaultFileSource::process(AbortAction &action) {
+ // Construct a cancellation response.
+ auto res = util::make_unique<Response>();
+ res->status = Response::Error;
+ res->message = "Environment is terminating";
+ std::shared_ptr<const Response> response = std::move(res);
+
+ // Iterate through all pending requests and remove them in case they're abandoned.
+ util::erase_if(pending, [&](const std::pair<Resource, SharedRequestBase *> &it) -> bool {
+ // Obtain all pending requests that are in the current environment.
+ const auto aborted = it.second->removeAllInEnvironment(action.env);
+
+ // Notify all observers.
+ for (auto req : aborted) {
+ req->notify(response);
+ }
+
+ // Finally, remove all requests that are now abandoned.
+ if (it.second->abandoned()) {
+ it.second->cancel();
+ return true;
+ } else {
+ return false;
+ }
+ });
+}
+
void DefaultFileSource::notify(SharedRequestBase *sharedRequest,
const std::set<Request *> &observers,
std::shared_ptr<const Response> response, FileCache::Hint hint) {
@@ -235,8 +273,8 @@ void DefaultFileSource::notify(SharedRequestBase *sharedRequest,
}
// Notify all observers.
- for (auto it : observers) {
- it->notify(response);
+ for (auto req : observers) {
+ req->notify(response);
}
}
diff --git a/src/mbgl/storage/request.cpp b/src/mbgl/storage/request.cpp
index de18138ec2..48b5b774d2 100644
--- a/src/mbgl/storage/request.cpp
+++ b/src/mbgl/storage/request.cpp
@@ -13,8 +13,8 @@
namespace mbgl {
// Note: This requires that loop is running in the current thread (or not yet running).
-Request::Request(const Resource &resource_, uv_loop_t *loop, Callback callback_)
- : callback(callback_), resource(resource_) {
+Request::Request(const Resource &resource_, uv_loop_t *loop, const Environment &env_, Callback callback_)
+ : callback(callback_), resource(resource_), env(env_) {
// When there is no loop supplied (== nullptr), the callback will be fired in an arbitrary
// thread (the thread notify() is called from) rather than kicking back to the calling thread.
if (loop) {