summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/mbgl/android/native_map_view.hpp3
-rw-r--r--include/mbgl/storage/default/sqlite_cache.hpp42
-rw-r--r--include/mbgl/storage/file_cache.hpp4
-rw-r--r--include/mbgl/util/run_loop.hpp52
-rw-r--r--include/mbgl/util/thread.hpp52
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