diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/mbgl/android/native_map_view.hpp | 3 | ||||
-rw-r--r-- | include/mbgl/storage/default/sqlite_cache.hpp | 42 | ||||
-rw-r--r-- | include/mbgl/storage/file_cache.hpp | 4 | ||||
-rw-r--r-- | include/mbgl/util/run_loop.hpp | 52 | ||||
-rw-r--r-- | include/mbgl/util/thread.hpp | 52 |
5 files changed, 124 insertions, 29 deletions
diff --git a/include/mbgl/android/native_map_view.hpp b/include/mbgl/android/native_map_view.hpp index 21784f5315..4a8d9365bf 100644 --- a/include/mbgl/android/native_map_view.hpp +++ b/include/mbgl/android/native_map_view.hpp @@ -4,6 +4,7 @@ #include <mbgl/map/map.hpp> #include <mbgl/map/view.hpp> #include <mbgl/util/noncopyable.hpp> +#include <mbgl/util/thread.hpp> #include <mbgl/storage/default/sqlite_cache.hpp> #include <mbgl/storage/default_file_source.hpp> @@ -61,7 +62,7 @@ private: ANativeWindow *window = nullptr; - mbgl::SQLiteCache fileCache; + mbgl::util::Thread<mbgl::SQLiteCache> fileCache; mbgl::DefaultFileSource fileSource; mbgl::Map map; diff --git a/include/mbgl/storage/default/sqlite_cache.hpp b/include/mbgl/storage/default/sqlite_cache.hpp index fe80a41b52..899cc8a892 100644 --- a/include/mbgl/storage/default/sqlite_cache.hpp +++ b/include/mbgl/storage/default/sqlite_cache.hpp @@ -2,50 +2,40 @@ #define MBGL_STORAGE_DEFAULT_SQLITE_CACHE #include <mbgl/storage/file_cache.hpp> +#include <mbgl/util/run_loop.hpp> #include <string> -#include <thread> -typedef struct uv_loop_s uv_loop_t; - -namespace mapbox { namespace util { template<typename... Types> class variant; } } namespace mapbox { namespace sqlite { class Database; class Statement; } } namespace mbgl { -namespace util { template <typename T> class AsyncQueue; } - -class SQLiteCache : public FileCache { - struct GetAction; - struct PutAction; - struct RefreshAction; - struct StopAction; - using Action = mapbox::util::variant<GetAction, PutAction, RefreshAction, StopAction>; - using Queue = util::AsyncQueue<Action>; +class SQLiteCache : public FileCache, protected util::RunLoop { + friend class util::Thread<SQLiteCache>; -public: +private: SQLiteCache(const std::string &path = ":memory:"); ~SQLiteCache(); - void get(const Resource &resource, std::function<void(std::unique_ptr<Response>)> callback); - void put(const Resource &resource, std::shared_ptr<const Response> response, Hint hint); +public: + // FileCache API + void get(const Resource &resource, Callback callback) override; + void put(const Resource &resource, std::shared_ptr<const Response> response, Hint hint) override; private: - struct ActionDispatcher; - void process(GetAction &action); - void process(PutAction &action); - void process(RefreshAction &action); - void process(StopAction &action); - void createDatabase(); void createSchema(); + void processGet(const Resource& resource, Callback callback); + void processPut(const Resource& resource, std::shared_ptr<const Response> response); + void processRefresh(const Resource& resource, int64_t expires); + +private: const std::string path; - uv_loop_t *loop = nullptr; - Queue *queue = nullptr; - std::thread thread; std::unique_ptr<::mapbox::sqlite::Database> db; - std::unique_ptr<::mapbox::sqlite::Statement> getStmt, putStmt, refreshStmt; + std::unique_ptr<::mapbox::sqlite::Statement> getStmt; + std::unique_ptr<::mapbox::sqlite::Statement> putStmt; + std::unique_ptr<::mapbox::sqlite::Statement> refreshStmt; bool schema = false; }; diff --git a/include/mbgl/storage/file_cache.hpp b/include/mbgl/storage/file_cache.hpp index 97e75a5d85..f815d5b8c2 100644 --- a/include/mbgl/storage/file_cache.hpp +++ b/include/mbgl/storage/file_cache.hpp @@ -16,9 +16,9 @@ public: virtual ~FileCache() = default; enum class Hint : uint8_t { Full, Refresh, No }; + using Callback = std::function<void(std::unique_ptr<Response>)>; - virtual void get(const Resource &resource, - std::function<void(std::unique_ptr<Response>)> callback) = 0; + virtual void get(const Resource &resource, Callback callback) = 0; virtual void put(const Resource &resource, std::shared_ptr<const Response> response, Hint hint) = 0; }; diff --git a/include/mbgl/util/run_loop.hpp b/include/mbgl/util/run_loop.hpp new file mode 100644 index 0000000000..f0318d2026 --- /dev/null +++ b/include/mbgl/util/run_loop.hpp @@ -0,0 +1,52 @@ +#ifndef MBGL_UTIL_RUN_LOOP +#define MBGL_UTIL_RUN_LOOP + +#include <mutex> +#include <functional> +#include <queue> + +namespace uv { +class async; +class loop; +} + +namespace mbgl { +namespace util { + +template <typename T> class Thread; + +class RunLoop { + friend Thread<RunLoop>; + +protected: + // These are called by the Thread<> wrapper. + RunLoop(); + ~RunLoop(); + + // Called by the Thread<> wrapper to start the loop. When you implement this + // method in a child class, you *must* call this function as the last action. + void start(); + +protected: + // Called by the Thread<> wrapper to terminate this loop. + void stop(); + +private: + // Invokes function in the run loop. + void process(); + +public: + // Schedules a function to be executed as part of this run loop. + void invoke(std::function<void()> fn); + +private: + const std::unique_ptr<uv::loop> runloop; + const std::unique_ptr<uv::async> runloopAsync; + std::mutex runloopMutex; + std::queue<std::function<void()>> runloopQueue; +}; + +} +} + +#endif
\ No newline at end of file diff --git a/include/mbgl/util/thread.hpp b/include/mbgl/util/thread.hpp new file mode 100644 index 0000000000..943039c5d6 --- /dev/null +++ b/include/mbgl/util/thread.hpp @@ -0,0 +1,52 @@ +#ifndef MBGL_UTIL_THREAD +#define MBGL_UTIL_THREAD + +#include <future> +#include <thread> + +namespace mbgl { +namespace util { + +template <class Object> +class Thread { +public: + template <class... Args> + Thread(Args&&... args); + Thread(const Thread&) = delete; + Thread(Thread&&) = delete; + Thread& operator=(const Thread&) = delete; + Thread& operator=(Thread&&) = delete; + ~Thread(); + + inline Object* operator->() const { return &object; } + inline operator Object*() const { return &object; } + +private: + std::thread thread; + Object& object; +}; + +template <class Object> +template <class... Args> +Thread<Object>::Thread(Args&&... args) + : object([&]() -> Object& { + std::promise<Object&> promise; + thread = std::thread([&] { + Object context(::std::forward<Args>(args)...); + promise.set_value(context); + context.start(); + }); + return promise.get_future().get(); + }()) { +} + +template <class Object> +Thread<Object>::~Thread() { + object.stop(); + thread.join(); +} + +} +} + +#endif |