diff options
author | Konstantin Käfer <mail@kkaefer.com> | 2015-04-13 18:28:18 +0200 |
---|---|---|
committer | Konstantin Käfer <mail@kkaefer.com> | 2015-04-13 18:28:18 +0200 |
commit | 452d12e6e653d61c2182f4464d4365f0b96c9739 (patch) | |
tree | a96bcdba373ca23d832364d7bce6b5912864c1f5 /src/mbgl/storage | |
parent | 16849a341b72c0633be1e3c89498c883d6efb000 (diff) | |
download | qtlocation-mapboxgl-452d12e6e653d61c2182f4464d4365f0b96c9739.tar.gz |
make implementation files private headers
Diffstat (limited to 'src/mbgl/storage')
-rw-r--r-- | src/mbgl/storage/asset_request.hpp | 24 | ||||
-rw-r--r-- | src/mbgl/storage/default_file_source.cpp | 7 | ||||
-rw-r--r-- | src/mbgl/storage/default_file_source_impl.hpp | 40 | ||||
-rw-r--r-- | src/mbgl/storage/http_context.hpp | 76 | ||||
-rw-r--r-- | src/mbgl/storage/http_request.hpp | 26 | ||||
-rw-r--r-- | src/mbgl/storage/request.cpp | 2 | ||||
-rw-r--r-- | src/mbgl/storage/request.hpp | 60 | ||||
-rw-r--r-- | src/mbgl/storage/shared_request_base.hpp | 106 | ||||
-rw-r--r-- | src/mbgl/storage/thread_context.hpp | 78 |
9 files changed, 414 insertions, 5 deletions
diff --git a/src/mbgl/storage/asset_request.hpp b/src/mbgl/storage/asset_request.hpp new file mode 100644 index 0000000000..48d421c3be --- /dev/null +++ b/src/mbgl/storage/asset_request.hpp @@ -0,0 +1,24 @@ +#ifndef MBGL_STORAGE_DEFAULT_ASSET_REQUEST +#define MBGL_STORAGE_DEFAULT_ASSET_REQUEST + +#include "shared_request_base.hpp" + +namespace mbgl { + +class AssetRequest : public SharedRequestBase { +public: + AssetRequest(DefaultFileSource::Impl *source, const Resource &resource); + + void start(uv_loop_t *loop, std::shared_ptr<const Response> response = nullptr); + void cancel(); + +private: + ~AssetRequest(); + void *ptr = nullptr; + + friend class AssetRequestImpl; +}; + +} + +#endif diff --git a/src/mbgl/storage/default_file_source.cpp b/src/mbgl/storage/default_file_source.cpp index ee4042459b..b28e096414 100644 --- a/src/mbgl/storage/default_file_source.cpp +++ b/src/mbgl/storage/default_file_source.cpp @@ -1,7 +1,7 @@ #include <mbgl/storage/default_file_source_impl.hpp> -#include <mbgl/storage/default/request.hpp> -#include <mbgl/storage/default/asset_request.hpp> -#include <mbgl/storage/default/http_request.hpp> +#include <mbgl/storage/request.hpp> +#include <mbgl/storage/asset_request.hpp> +#include <mbgl/storage/http_request.hpp> #include <mbgl/storage/response.hpp> #include <mbgl/platform/platform.hpp> @@ -9,7 +9,6 @@ #include <mbgl/util/uv_detail.hpp> #include <mbgl/util/chrono.hpp> #include <mbgl/util/thread.hpp> -#include <mbgl/util/run_loop.hpp> #include <mbgl/platform/log.hpp> #pragma GCC diagnostic push diff --git a/src/mbgl/storage/default_file_source_impl.hpp b/src/mbgl/storage/default_file_source_impl.hpp new file mode 100644 index 0000000000..82a3b9a1a0 --- /dev/null +++ b/src/mbgl/storage/default_file_source_impl.hpp @@ -0,0 +1,40 @@ +#ifndef MBGL_STORAGE_DEFAULT_DEFAULT_FILE_SOURCE_IMPL +#define MBGL_STORAGE_DEFAULT_DEFAULT_FILE_SOURCE_IMPL + +#include <mbgl/storage/default_file_source.hpp> +#include <mbgl/util/run_loop.hpp> + +#include <set> +#include <unordered_map> + +namespace mbgl { + +class SharedRequestBase; + +class DefaultFileSource::Impl : public util::RunLoop { + friend class util::Thread<DefaultFileSource::Impl>; + +public: + Impl(FileCache *cache, const std::string &root = ""); + +public: + void notify(SharedRequestBase *sharedRequest, const std::set<Request *> &observers, + std::shared_ptr<const Response> response, FileCache::Hint hint); + SharedRequestBase *find(const Resource &resource); + + void processAdd(Request* request); + void processCancel(Request* request); + void processResult(const Resource& resource, std::shared_ptr<const Response> response); + void processAbort(const Environment& env); + +public: + const std::string assetRoot; + +private: + std::unordered_map<Resource, SharedRequestBase *, Resource::Hash> pending; + FileCache *cache = nullptr; +}; + +} + +#endif diff --git a/src/mbgl/storage/http_context.hpp b/src/mbgl/storage/http_context.hpp new file mode 100644 index 0000000000..6b9518dab3 --- /dev/null +++ b/src/mbgl/storage/http_context.hpp @@ -0,0 +1,76 @@ +#ifndef MBGL_STORAGE_DEFAULT_HTTP_CONTEXT +#define MBGL_STORAGE_DEFAULT_HTTP_CONTEXT + +#include "thread_context.hpp" +#include <mbgl/storage/network_status.hpp> + +#include <set> + +namespace mbgl { + +class HTTPRequest; + +// This is a template class that provides a per-thread Context object. It can be used by HTTP +// implementations to store global state. It also implements the NetworkStatus mechanism and +// triggers immediate retries on all requests waiting for network status changes. + +template <typename Context> +class HTTPContext : public ThreadContext<Context> { +public: + HTTPContext(uv_loop_t *loop); + ~HTTPContext(); + + void addRequest(HTTPRequest *request); + void removeRequest(HTTPRequest *baton); + +public: + // Will be fired when the network status becomes reachable. + uv_async_t *reachability = nullptr; + + // A list of all pending HTTPRequestImpls that we need to notify when the network status + // changes. + std::set<HTTPRequest *> requests; +}; + +template <typename Context> +HTTPContext<Context>::HTTPContext(uv_loop_t *loop_) + : ThreadContext<Context>(loop_) { + reachability = new uv_async_t; + reachability->data = this; +#if UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR <= 10 + uv_async_init(loop_, reachability, [](uv_async_t *async, int) { +#else + uv_async_init(loop_, reachability, [](uv_async_t *async) { +#endif + for (auto request : reinterpret_cast<Context *>(async->data)->requests) { + request->retryImmediately(); + } + }); + // Allow the loop to quit even though this handle is still active. + uv_unref(reinterpret_cast<uv_handle_t *>(reachability)); + NetworkStatus::Subscribe(reachability); +} + +template <typename Context> +HTTPContext<Context>::~HTTPContext() { + MBGL_VERIFY_THREAD(HTTPContext<Context>::tid); + + assert(requests.empty()); + + NetworkStatus::Unsubscribe(reachability); + uv::close(reachability); +} + +template <typename Context> +void HTTPContext<Context>::addRequest(HTTPRequest *request) { + requests.insert(request); +} + +template <typename Context> +void HTTPContext<Context>::removeRequest(HTTPRequest *request) { + requests.erase(request); +} + +} + +#endif diff --git a/src/mbgl/storage/http_request.hpp b/src/mbgl/storage/http_request.hpp new file mode 100644 index 0000000000..54e9a77ef0 --- /dev/null +++ b/src/mbgl/storage/http_request.hpp @@ -0,0 +1,26 @@ +#ifndef MBGL_STORAGE_DEFAULT_HTTP_REQUEST +#define MBGL_STORAGE_DEFAULT_HTTP_REQUEST + +#include "shared_request_base.hpp" + +namespace mbgl { + +class HTTPRequest : public SharedRequestBase { +public: + HTTPRequest(DefaultFileSource::Impl *source, const Resource &resource); + + void start(uv_loop_t *loop, std::shared_ptr<const Response> response = nullptr); + void cancel(); + + void retryImmediately(); + +private: + ~HTTPRequest(); + void *ptr = nullptr; + + friend class HTTPRequestImpl; +}; + +} + +#endif diff --git a/src/mbgl/storage/request.cpp b/src/mbgl/storage/request.cpp index ed7f625e86..ea80e59503 100644 --- a/src/mbgl/storage/request.cpp +++ b/src/mbgl/storage/request.cpp @@ -1,4 +1,4 @@ -#include <mbgl/storage/default/request.hpp> +#include <mbgl/storage/request.hpp> #include <mbgl/storage/response.hpp> diff --git a/src/mbgl/storage/request.hpp b/src/mbgl/storage/request.hpp new file mode 100644 index 0000000000..00157329be --- /dev/null +++ b/src/mbgl/storage/request.hpp @@ -0,0 +1,60 @@ +#ifndef MBGL_STORAGE_DEFAULT_REQUEST +#define MBGL_STORAGE_DEFAULT_REQUEST + +#include <mbgl/storage/resource.hpp> + +#include <mbgl/util/util.hpp> +#include <mbgl/util/noncopyable.hpp> + +#include <mutex> +#include <thread> +#include <functional> +#include <memory> + +typedef struct uv_async_s uv_async_t; +typedef struct uv_loop_s uv_loop_t; + +namespace mbgl { + +class Response; +class Environment; + +class Request : private util::noncopyable { + MBGL_STORE_THREAD(tid) + +public: + using Callback = std::function<void(const Response &)>; + Request(const Resource &resource, uv_loop_t *loop, const Environment &env, Callback callback); + +public: + // May be called from any thread. + void notify(const std::shared_ptr<const Response> &response); + void destruct(); + + // May be called only from the thread the Request was created in. + void cancel(); + +private: + ~Request(); + void invoke(); + void notifyCallback(); + +private: + uv_async_t *async = nullptr; + struct Canceled; + std::unique_ptr<Canceled> canceled; + Callback callback; + std::shared_ptr<const Response> response; + +public: + const Resource resource; + + // The environment ref is used to associate requests with a particular environment. This allows + // us to only terminate requests associated with that environment, e.g. when the map the env + // belongs to is discarded. + const Environment &env; +}; + +} + +#endif diff --git a/src/mbgl/storage/shared_request_base.hpp b/src/mbgl/storage/shared_request_base.hpp new file mode 100644 index 0000000000..d7ed00264a --- /dev/null +++ b/src/mbgl/storage/shared_request_base.hpp @@ -0,0 +1,106 @@ +#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); + + if (source) { + source->notify(this, observers, response, hint); + } + } + + void subscribe(Request *request) { + MBGL_VERIFY_THREAD(tid); + + observers.insert(request); + } + + void unsubscribe(Request *request) { + MBGL_VERIFY_THREAD(tid); + + observers.erase(request); + + if (abandoned()) { + // There are no observers anymore. We are initiating cancelation. + if (source) { + // First, remove this SharedRequestBase from the source. + source->notify(this, observers, nullptr, FileCache::Hint::No); + } + + // Then, initiate cancelation of this request + cancel(); + } + } + + 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; + +protected: + DefaultFileSource::Impl *source = nullptr; + +private: + std::set<Request *> observers; +}; + +} + +#endif diff --git a/src/mbgl/storage/thread_context.hpp b/src/mbgl/storage/thread_context.hpp new file mode 100644 index 0000000000..763c83a25b --- /dev/null +++ b/src/mbgl/storage/thread_context.hpp @@ -0,0 +1,78 @@ +#ifndef MBGL_STORAGE_DEFAULT_THREAD_CONTEXT +#define MBGL_STORAGE_DEFAULT_THREAD_CONTEXT + +#include <mbgl/util/noncopyable.hpp> +#include <mbgl/util/std.hpp> +#include <mbgl/util/util.hpp> +#include <mbgl/util/uv.hpp> + +#include <uv.h> +#include <pthread.h> + +#include <map> +#include <cassert> + +namespace mbgl { + +// This is a template class that provides a per-thread and per-loop Context object. It can be used +// by implementations to store global state. + +template <typename Context> +class ThreadContext : private util::noncopyable { +protected: + MBGL_STORE_THREAD(tid) + using Map = std::map<uv_loop_t *, std::unique_ptr<Context>>; + +public: + static Context *Get(uv_loop_t *loop); + +private: + static pthread_key_t key; + static pthread_once_t once; + +public: + ThreadContext(uv_loop_t *loop); + ~ThreadContext(); + +public: + uv_loop_t *loop; +}; + +template <typename Context> +Context *ThreadContext<Context>::Get(uv_loop_t *loop) { + pthread_once(&once, []() { + pthread_key_create(&key, [](void *ptr) { + assert(ptr); + delete reinterpret_cast<Map *>(ptr); + }); + }); + auto contexts = reinterpret_cast<Map *>(pthread_getspecific(key)); + if (!contexts) { + contexts = new Map(); + pthread_setspecific(key, contexts); + } + + // Now find a ThreadContext that matches the requested loop. + auto it = contexts->find(loop); + if (it == contexts->end()) { + auto result = contexts->emplace(loop, util::make_unique<Context>(loop)); + assert(result.second); // Make sure it was actually inserted. + return result.first->second.get(); + } else { + return it->second.get(); + } +} + +template <typename Context> +ThreadContext<Context>::ThreadContext(uv_loop_t *loop_) : loop(loop_) { +} + +template <typename Context> +ThreadContext<Context>::~ThreadContext() { + MBGL_VERIFY_THREAD(tid); +} + + +} + +#endif |