summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2015-04-17 09:58:24 -0700
committerJohn Firebaugh <john.firebaugh@gmail.com>2015-04-28 09:16:26 -0400
commitcdd8f3ac3235e1d5aab47a6d32c48a0b82a3a1b9 (patch)
treebcfa045fa4527a6f3fba094b49ecb981f671425d
parent359aca6624f183099a9afe58aae5a41bd2cb3772 (diff)
downloadqtlocation-mapboxgl-cdd8f3ac3235e1d5aab47a6d32c48a0b82a3a1b9.tar.gz
Separate RequestBase from DefaultFileSource internals
SharedRequestBase was trying to do two different jobs: be a base class for Asset/HttpRequest and track internal state for DefaultFileSource. Now we have RequestBase for the former, and DefaultFileRequest for the latter.
-rw-r--r--platform/darwin/http_request_nsurl.mm13
-rw-r--r--platform/default/asset_request_fs.cpp11
-rw-r--r--platform/default/asset_request_zip.cpp13
-rw-r--r--platform/default/http_request_curl.cpp13
-rw-r--r--src/mbgl/storage/asset_request.hpp6
-rw-r--r--src/mbgl/storage/default_file_source.cpp208
-rw-r--r--src/mbgl/storage/default_file_source_impl.hpp37
-rw-r--r--src/mbgl/storage/http_request.hpp8
-rw-r--r--src/mbgl/storage/request_base.hpp39
-rw-r--r--src/mbgl/storage/shared_request_base.hpp95
10 files changed, 191 insertions, 252 deletions
diff --git a/platform/darwin/http_request_nsurl.mm b/platform/darwin/http_request_nsurl.mm
index 24b31ae0a9..07ac16e058 100644
--- a/platform/darwin/http_request_nsurl.mm
+++ b/platform/darwin/http_request_nsurl.mm
@@ -1,5 +1,6 @@
#include <mbgl/storage/http_request.hpp>
#include <mbgl/storage/http_context.hpp>
+#include <mbgl/storage/resource.hpp>
#include <mbgl/storage/response.hpp>
#include <mbgl/util/uv.hpp>
@@ -397,36 +398,28 @@ void HTTPRequestImpl::restart(uv_timer_t *timer, int) {
// -------------------------------------------------------------------------------------------------
-HTTPRequest::HTTPRequest(DefaultFileSource::Impl &source, const Resource &resource)
- : SharedRequestBase(source, resource) {
+HTTPRequest::HTTPRequest(const Resource& resource, Callback callback)
+ : RequestBase(resource, callback) {
}
HTTPRequest::~HTTPRequest() {
- MBGL_VERIFY_THREAD(tid);
-
if (ptr) {
reinterpret_cast<HTTPRequestImpl *>(ptr)->cancel();
}
}
void HTTPRequest::start(uv_loop_t *loop, std::shared_ptr<const Response> response) {
- MBGL_VERIFY_THREAD(tid);
-
assert(!ptr);
ptr = new HTTPRequestImpl(this, loop, response);
}
void HTTPRequest::retryImmediately() {
- MBGL_VERIFY_THREAD(tid);
-
if (ptr) {
reinterpret_cast<HTTPRequestImpl *>(ptr)->retryImmediately();
}
}
void HTTPRequest::cancel() {
- MBGL_VERIFY_THREAD(tid);
-
delete this;
}
diff --git a/platform/default/asset_request_fs.cpp b/platform/default/asset_request_fs.cpp
index 446f2f3d52..9580c2f5bc 100644
--- a/platform/default/asset_request_fs.cpp
+++ b/platform/default/asset_request_fs.cpp
@@ -1,4 +1,5 @@
#include <mbgl/storage/asset_request.hpp>
+#include <mbgl/storage/resource.hpp>
#include <mbgl/storage/response.hpp>
#include <mbgl/util/std.hpp>
#include <mbgl/util/util.hpp>
@@ -207,23 +208,19 @@ void AssetRequestImpl::cleanup(uv_fs_t *req) {
// -------------------------------------------------------------------------------------------------
-AssetRequest::AssetRequest(DefaultFileSource::Impl &source_, const Resource &resource_, const std::string& assetRoot_)
- : SharedRequestBase(source_, resource_)
+AssetRequest::AssetRequest(const Resource& resource_, Callback callback_, const std::string& assetRoot_)
+ : RequestBase(resource_, callback_)
, assetRoot(assetRoot_) {
assert(algo::starts_with(resource.url, "asset://"));
}
AssetRequest::~AssetRequest() {
- MBGL_VERIFY_THREAD(tid);
-
if (ptr) {
reinterpret_cast<AssetRequestImpl *>(ptr)->request = nullptr;
}
}
void AssetRequest::start(uv_loop_t *loop, std::shared_ptr<const Response> response) {
- MBGL_VERIFY_THREAD(tid);
-
// We're ignoring the existing response if any.
(void(response));
@@ -233,8 +230,6 @@ void AssetRequest::start(uv_loop_t *loop, std::shared_ptr<const Response> respon
}
void AssetRequest::cancel() {
- MBGL_VERIFY_THREAD(tid);
-
if (ptr) {
reinterpret_cast<AssetRequestImpl *>(ptr)->canceled = true;
diff --git a/platform/default/asset_request_zip.cpp b/platform/default/asset_request_zip.cpp
index 8a471a4fc4..69de1c742c 100644
--- a/platform/default/asset_request_zip.cpp
+++ b/platform/default/asset_request_zip.cpp
@@ -1,6 +1,7 @@
#include <mbgl/storage/asset_request.hpp>
#include <mbgl/storage/thread_context.hpp>
#include <mbgl/android/jni.hpp>
+#include <mbgl/storage/resource.hpp>
#include <mbgl/storage/response.hpp>
#include <mbgl/platform/log.hpp>
#include <mbgl/util/std.hpp>
@@ -107,7 +108,7 @@ AssetRequestImpl::~AssetRequestImpl() {
MBGL_VERIFY_THREAD(tid);
if (request) {
- request->ptr = nullptr;
+ request->impl = nullptr;
}
}
@@ -274,23 +275,19 @@ void AssetRequestImpl::cancel() {
// -------------------------------------------------------------------------------------------------
-AssetRequest::AssetRequest(DefaultFileSource::Impl &source_, const Resource &resource_, const std::string& assetRoot_)
- : SharedRequestBase(source_, resource_)
+AssetRequest::AssetRequest(const Resource& resource_, Callback callback_, const std::string& assetRoot_)
+ : RequestBase(resource_, callback_)
, assetRoot(assetRoot_) {
assert(algo::starts_with(resource.url, "asset://"));
}
AssetRequest::~AssetRequest() {
- MBGL_VERIFY_THREAD(tid);
-
if (ptr) {
reinterpret_cast<AssetRequestImpl *>(ptr)->cancel();
}
}
void AssetRequest::start(uv_loop_t *loop, std::shared_ptr<const Response> response) {
- MBGL_VERIFY_THREAD(tid);
-
// We're ignoring the existing response if any.
(void(response));
@@ -300,8 +297,6 @@ void AssetRequest::start(uv_loop_t *loop, std::shared_ptr<const Response> respon
}
void AssetRequest::cancel() {
- MBGL_VERIFY_THREAD(tid);
-
if (ptr) {
reinterpret_cast<AssetRequestImpl *>(ptr)->cancel();
}
diff --git a/platform/default/http_request_curl.cpp b/platform/default/http_request_curl.cpp
index a5de61104a..ffe3b525ab 100644
--- a/platform/default/http_request_curl.cpp
+++ b/platform/default/http_request_curl.cpp
@@ -1,5 +1,6 @@
#include <mbgl/storage/http_request.hpp>
#include <mbgl/storage/http_context.hpp>
+#include <mbgl/storage/resource.hpp>
#include <mbgl/storage/response.hpp>
#include <mbgl/util/chrono.hpp>
#include <mbgl/platform/log.hpp>
@@ -722,36 +723,28 @@ void HTTPRequestImpl::handleResult(CURLcode code) {
// -------------------------------------------------------------------------------------------------
-HTTPRequest::HTTPRequest(DefaultFileSource::Impl &source_, const Resource &resource_)
- : SharedRequestBase(source_, resource_) {
+HTTPRequest::HTTPRequest(const Resource& resource_, Callback callback_)
+ : RequestBase(resource_, callback_) {
}
HTTPRequest::~HTTPRequest() {
- MBGL_VERIFY_THREAD(tid);
-
if (ptr) {
reinterpret_cast<HTTPRequestImpl *>(ptr)->abandon();
}
}
void HTTPRequest::start(uv_loop_t *loop, std::shared_ptr<const Response> response) {
- MBGL_VERIFY_THREAD(tid);
-
assert(!ptr);
ptr = new HTTPRequestImpl(this, loop, response);
}
void HTTPRequest::retryImmediately() {
- MBGL_VERIFY_THREAD(tid);
-
if (ptr) {
reinterpret_cast<HTTPRequestImpl *>(ptr)->retryImmediately();
}
}
void HTTPRequest::cancel() {
- MBGL_VERIFY_THREAD(tid);
-
if (ptr) {
delete reinterpret_cast<HTTPRequestImpl *>(ptr);
ptr = nullptr;
diff --git a/src/mbgl/storage/asset_request.hpp b/src/mbgl/storage/asset_request.hpp
index 2a571d2093..e20e1d818a 100644
--- a/src/mbgl/storage/asset_request.hpp
+++ b/src/mbgl/storage/asset_request.hpp
@@ -1,13 +1,13 @@
#ifndef MBGL_STORAGE_DEFAULT_ASSET_REQUEST
#define MBGL_STORAGE_DEFAULT_ASSET_REQUEST
-#include "shared_request_base.hpp"
+#include "request_base.hpp"
namespace mbgl {
-class AssetRequest : public SharedRequestBase {
+class AssetRequest : public RequestBase {
public:
- AssetRequest(DefaultFileSource::Impl&, const Resource&, const std::string& assetRoot);
+ AssetRequest(const Resource&, Callback, const std::string& assetRoot);
void start(uv_loop_t *loop, std::shared_ptr<const Response> response = nullptr);
void cancel();
diff --git a/src/mbgl/storage/default_file_source.cpp b/src/mbgl/storage/default_file_source.cpp
index f4c220e36f..c510b5c7f1 100644
--- a/src/mbgl/storage/default_file_source.cpp
+++ b/src/mbgl/storage/default_file_source.cpp
@@ -28,10 +28,6 @@ namespace algo = boost::algorithm;
namespace mbgl {
-DefaultFileSource::Impl::Impl(FileCache* cache_, const std::string& root)
- : assetRoot(root.empty() ? platform::assetRoot() : root), cache(cache_) {
-}
-
DefaultFileSource::DefaultFileSource(FileCache* cache, const std::string& root)
: thread(util::make_unique<util::Thread<Impl>>("FileSource", cache, root)) {
}
@@ -40,18 +36,6 @@ DefaultFileSource::~DefaultFileSource() {
MBGL_VERIFY_THREAD(tid);
}
-SharedRequestBase *DefaultFileSource::Impl::find(const Resource &resource) {
- // We're using a set of pointers here instead of a map between url and SharedRequestBase because
- // we need to find the requests both by pointer and by URL. Given that the number of requests
- // is generally very small (typically < 10 at a time), hashing by URL incurs too much overhead
- // anyway.
- const auto it = pending.find(resource);
- if (it != pending.end()) {
- return it->second;
- }
- return nullptr;
-}
-
Request* DefaultFileSource::request(const Resource& resource,
uv_loop_t* l,
const Environment& env,
@@ -81,52 +65,95 @@ void DefaultFileSource::abort(const Environment &env) {
thread->invoke(&Impl::abort, std::ref(env));
}
+// ----- Impl -----
+
+DefaultFileSource::Impl::Impl(FileCache* cache_, const std::string& root)
+ : cache(cache_), assetRoot(root.empty() ? platform::assetRoot() : root) {
+}
+
+DefaultFileRequest* DefaultFileSource::Impl::find(const Resource& resource) {
+ const auto it = pending.find(resource);
+ if (it != pending.end()) {
+ return &it->second;
+ }
+ return nullptr;
+}
+
void DefaultFileSource::Impl::add(Request* req, uv_loop_t* loop) {
- const Resource &resource = req->resource;
-
- // We're adding a new Request.
- SharedRequestBase *sharedRequest = find(resource);
- if (!sharedRequest) {
- // There is no request for this URL yet. Create a new one and start it.
- if (algo::starts_with(resource.url, "asset://")) {
- sharedRequest = new AssetRequest(*this, resource, assetRoot);
- } else {
- sharedRequest = new HTTPRequest(*this, resource);
+ const Resource& resource = req->resource;
+ DefaultFileRequest* request = find(resource);
+
+ if (request) {
+ request->observers.insert(req);
+ return;
+ }
+
+ request = &pending.emplace(resource, DefaultFileRequest(resource, loop)).first->second;
+ request->observers.insert(req);
+
+ if (cache) {
+ startCacheRequest(resource);
+ } else {
+ startRealRequest(resource);
+ }
+}
+
+void DefaultFileSource::Impl::startCacheRequest(const Resource& resource) {
+ // Check the cache for existing data so that we can potentially
+ // revalidate the information without having to redownload everything.
+ cache->get(resource, [this, resource](std::unique_ptr<Response> response) {
+ DefaultFileRequest* request = find(resource);
+
+ if (!request) {
+ // There is no request for this URL anymore. Likely, the request was canceled
+ // before we got around to process the cache result.
+ return;
}
- const bool inserted = pending.emplace(resource, sharedRequest).second;
- assert(inserted);
- (void (inserted)); // silence unused variable warning on Release builds.
+ auto expired = [&response] {
+ const int64_t now = std::chrono::duration_cast<std::chrono::seconds>(
+ SystemClock::now().time_since_epoch()).count();
+ return response->expires <= now;
+ };
- // But first, we're going to start querying the database if it exists.
- if (!cache) {
- sharedRequest->start(loop);
+ if (!response || expired()) {
+ // No response or stale cache. Run the real request.
+ startRealRequest(resource, std::move(response));
} else {
- // Otherwise, first check the cache for existing data so that we can potentially
- // revalidate the information without having to redownload everything.
- cache->get(resource, [this, resource, loop](std::unique_ptr<Response> response) {
- processResult(resource, std::move(response), loop);
- });
+ // The response is fresh. We're good to notify the caller.
+ notify(request, std::move(response), FileCache::Hint::No);
}
+ });
+}
+
+void DefaultFileSource::Impl::startRealRequest(const Resource& resource, std::shared_ptr<const Response> response) {
+ DefaultFileRequest* request = find(resource);
+
+ auto callback = [request, this] (std::shared_ptr<const Response> res, FileCache::Hint hint) {
+ notify(request, res, hint);
+ };
+
+ if (algo::starts_with(resource.url, "asset://")) {
+ request->request = new AssetRequest(resource, callback, assetRoot);
+ } else {
+ request->request = new HTTPRequest(resource, callback);
}
- sharedRequest->subscribe(req);
+
+ request->request->start(request->loop, response);
}
void DefaultFileSource::Impl::cancel(Request* req) {
- SharedRequestBase *sharedRequest = find(req->resource);
- if (sharedRequest) {
- // If the number of dependent requests of the SharedRequestBase drops to zero, the
- // unsubscribe callback triggers the removal of the SharedRequestBase pointer from the list
- // of pending requests and initiates cancelation.
- sharedRequest->unsubscribe(req);
-
- if (sharedRequest->abandoned()) {
- // There are no observers anymore. We are initiating cancelation.
- // First, remove this SharedRequestBase from the source.
- pending.erase(sharedRequest->resource);
-
- // Then, initiate cancelation of this request
- sharedRequest->cancel();
+ DefaultFileRequest* request = find(req->resource);
+
+ if (request) {
+ // If the number of dependent requests of the DefaultFileRequest drops to zero,
+ // cancel the request and remove it from the pending list.
+ request->observers.erase(req);
+ if (request->observers.empty()) {
+ if (request->request) {
+ request->request->cancel();
+ }
+ pending.erase(request->resource);
}
} else {
// There is no request for this URL anymore. Likely, the request already completed
@@ -138,70 +165,51 @@ void DefaultFileSource::Impl::cancel(Request* req) {
req->destruct();
}
-void DefaultFileSource::Impl::processResult(const Resource& resource, std::shared_ptr<const Response> response, uv_loop_t* loop) {
- SharedRequestBase *sharedRequest = find(resource);
- if (sharedRequest) {
- if (response) {
- // This entry was stored in the cache. Now determine if we need to revalidate.
- const int64_t now = std::chrono::duration_cast<std::chrono::seconds>(
- SystemClock::now().time_since_epoch()).count();
- if (response->expires > now) {
- // The response is fresh. We're good to notify the caller.
- sharedRequest->notify(response, FileCache::Hint::No);
- sharedRequest->cancel();
- return;
- } else {
- // The cached response is stale. Now run the real request.
- sharedRequest->start(loop, response);
- }
- } else {
- // There is no response. Now run the real request.
- sharedRequest->start(loop);
- }
- } else {
- // There is no request for this URL anymore. Likely, the request was canceled
- // before we got around to process the cache result.
- }
-}
-
// Aborts all requests that are part of the current environment.
void DefaultFileSource::Impl::abort(const Environment& env) {
// 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);
+ auto response = std::make_shared<Response>();
+ response->status = Response::Error;
+ response->message = "Environment is terminating";
// 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(env);
+ util::erase_if(pending, [&](std::pair<const Resource, DefaultFileRequest>& it) -> bool {
+ // Notify all pending requests that are in the current environment.
+ util::erase_if(it.second.observers, [&](Request* req) -> bool {
+ if (&req->env == &env) {
+ req->notify(response);
+ return true;
+ } else {
+ return false;
+ }
+ });
- // Notify all observers.
- for (auto req : aborted) {
- req->notify(response);
- }
+ bool abandoned = it.second.observers.empty();
- // Finally, remove all requests that are now abandoned.
- if (it.second->abandoned()) {
- it.second->cancel();
- return true;
- } else {
- return false;
+ if (abandoned && it.second.request) {
+ it.second.request->cancel();
}
+
+ return abandoned;
});
}
-void DefaultFileSource::Impl::notify(SharedRequestBase *sharedRequest,
- std::shared_ptr<const Response> response, FileCache::Hint hint) {
+void DefaultFileSource::Impl::notify(DefaultFileRequest* request, std::shared_ptr<const Response> response, FileCache::Hint hint) {
// First, remove the request, since it might be destructed at any point now.
- assert(find(sharedRequest->resource) == sharedRequest);
- pending.erase(sharedRequest->resource);
+ assert(find(request->resource) == request);
+ assert(response);
+
+ // Notify all observers.
+ for (auto req : request->observers) {
+ req->notify(response);
+ }
if (cache) {
// Store response in database
- cache->put(sharedRequest->resource, response, hint);
+ cache->put(request->resource, response, hint);
}
+
+ pending.erase(request->resource);
}
}
diff --git a/src/mbgl/storage/default_file_source_impl.hpp b/src/mbgl/storage/default_file_source_impl.hpp
index 7a673b6ced..d3f83af38a 100644
--- a/src/mbgl/storage/default_file_source_impl.hpp
+++ b/src/mbgl/storage/default_file_source_impl.hpp
@@ -8,27 +8,36 @@
namespace mbgl {
-class SharedRequestBase;
+class RequestBase;
-class DefaultFileSource::Impl {
-public:
- Impl(FileCache *cache, const std::string &root = "");
+struct DefaultFileRequest {
+ const Resource resource;
+ uv_loop_t* loop;
+ std::set<Request*> observers;
+ RequestBase* request = nullptr;
- void notify(SharedRequestBase *sharedRequest,
- std::shared_ptr<const Response> response, FileCache::Hint hint);
- SharedRequestBase *find(const Resource &resource);
+ DefaultFileRequest(const Resource& resource_, uv_loop_t* loop_)
+ : resource(resource_), loop(loop_) {}
+};
- void add(Request* request, uv_loop_t* loop);
- void cancel(Request* request);
- void abort(const Environment& env);
+class DefaultFileSource::Impl {
+public:
+ Impl(FileCache*, const std::string& = "");
- const std::string assetRoot;
+ void add(Request*, uv_loop_t*);
+ void cancel(Request*);
+ void abort(const Environment&);
private:
- void processResult(const Resource& resource, std::shared_ptr<const Response> response, uv_loop_t* loop);
+ DefaultFileRequest* find(const Resource&);
- std::unordered_map<Resource, SharedRequestBase *, Resource::Hash> pending;
- FileCache *cache = nullptr;
+ void startCacheRequest(const Resource&);
+ void startRealRequest(const Resource&, std::shared_ptr<const Response> = nullptr);
+ void notify(DefaultFileRequest*, std::shared_ptr<const Response>, FileCache::Hint);
+
+ std::unordered_map<Resource, DefaultFileRequest, Resource::Hash> pending;
+ FileCache* cache = nullptr;
+ const std::string assetRoot;
};
}
diff --git a/src/mbgl/storage/http_request.hpp b/src/mbgl/storage/http_request.hpp
index 6232bd22e9..faf6ee2f1c 100644
--- a/src/mbgl/storage/http_request.hpp
+++ b/src/mbgl/storage/http_request.hpp
@@ -1,13 +1,15 @@
#ifndef MBGL_STORAGE_DEFAULT_HTTP_REQUEST
#define MBGL_STORAGE_DEFAULT_HTTP_REQUEST
-#include "shared_request_base.hpp"
+#include "request_base.hpp"
namespace mbgl {
-class HTTPRequest : public SharedRequestBase {
+struct Resource;
+
+class HTTPRequest : public RequestBase {
public:
- HTTPRequest(DefaultFileSource::Impl &source, const Resource &resource);
+ HTTPRequest(const Resource&, Callback);
void start(uv_loop_t *loop, std::shared_ptr<const Response> response = nullptr);
void cancel();
diff --git a/src/mbgl/storage/request_base.hpp b/src/mbgl/storage/request_base.hpp
new file mode 100644
index 0000000000..281e76a02c
--- /dev/null
+++ b/src/mbgl/storage/request_base.hpp
@@ -0,0 +1,39 @@
+#ifndef MBGL_STORAGE_REQUEST
+#define MBGL_STORAGE_REQUEST
+
+#include <mbgl/util/noncopyable.hpp>
+#include <mbgl/storage/file_cache.hpp>
+
+#include <memory>
+#include <functional>
+
+typedef struct uv_loop_s uv_loop_t;
+
+namespace mbgl {
+
+struct Resource;
+class Response;
+
+class RequestBase : private util::noncopyable {
+public:
+ using Callback = std::function<void (std::shared_ptr<const Response> response, FileCache::Hint hint)>;
+
+ RequestBase(const Resource& resource_, Callback notify_)
+ : notify(notify_)
+ , resource(resource_) {
+ }
+
+ virtual ~RequestBase() = default;
+
+ virtual void start(uv_loop_t *loop, std::shared_ptr<const Response> response = nullptr) = 0;
+ virtual void cancel() = 0;
+
+ Callback notify;
+
+protected:
+ const Resource& resource;
+};
+
+}
+
+#endif
diff --git a/src/mbgl/storage/shared_request_base.hpp b/src/mbgl/storage/shared_request_base.hpp
deleted file mode 100644
index cf70ac0f04..0000000000
--- a/src/mbgl/storage/shared_request_base.hpp
+++ /dev/null
@@ -1,95 +0,0 @@
-#ifndef MBGL_STORAGE_DEFAULT_SHARED_REQUEST_BASE
-#define MBGL_STORAGE_DEFAULT_SHARED_REQUEST_BASE
-
-#include <mbgl/storage/resource.hpp>
-#include <mbgl/storage/file_cache.hpp>
-#include <mbgl/storage/default_file_source_impl.hpp>
-#include <mbgl/storage/request.hpp>
-#include <mbgl/util/util.hpp>
-#include <mbgl/util/noncopyable.hpp>
-
-#include <string>
-#include <set>
-#include <vector>
-#include <cassert>
-
-typedef struct uv_loop_s uv_loop_t;
-
-namespace mbgl {
-
-class Request;
-class Response;
-class DefaultFileSource;
-
-class SharedRequestBase : private util::noncopyable {
-protected:
- MBGL_STORE_THREAD(tid)
-
-public:
- SharedRequestBase(DefaultFileSource::Impl &source_, const Resource &resource_)
- : resource(resource_), source(source_) {}
-
- virtual void start(uv_loop_t *loop, std::shared_ptr<const Response> response = nullptr) = 0;
- virtual void cancel() = 0;
-
- void notify(std::shared_ptr<const Response> response, FileCache::Hint hint) {
- MBGL_VERIFY_THREAD(tid);
- assert(response);
-
- source.notify(this, response, hint);
-
- // Notify all observers.
- for (auto req : observers) {
- req->notify(response);
- }
- }
-
- void subscribe(Request *request) {
- MBGL_VERIFY_THREAD(tid);
- observers.insert(request);
- }
-
- void unsubscribe(Request *request) {
- MBGL_VERIFY_THREAD(tid);
- observers.erase(request);
- }
-
- bool abandoned() const {
- return observers.empty();
- }
-
- std::vector<Request *> removeAllInEnvironment(const Environment &env) {
- MBGL_VERIFY_THREAD(tid);
-
- std::vector<Request *> result;
-
- // Removes all Requests in the supplied environment and returns a list
- // of them.
- util::erase_if(observers, [&](Request *req) -> bool {
- if (&req->env == &env) {
- result.push_back(req);
- return true;
- } else {
- return false;
- }
- });
-
- return result;
- }
-
-protected:
- virtual ~SharedRequestBase() {
- MBGL_VERIFY_THREAD(tid);
- }
-
-public:
- const Resource resource;
-
-private:
- DefaultFileSource::Impl& source;
- std::set<Request *> observers;
-};
-
-}
-
-#endif