From b9bf66e67ed1d0d1b1d3163255cab099a6ba4a95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Konstantin=20K=C3=A4fer?= Date: Fri, 16 Jan 2015 14:04:41 +0100 Subject: rewrite storage layer to be independent of the Map's event loop --- include/mbgl/util/async_queue.hpp | 95 +++++++++++++++++++++++++++++++++++++++ include/mbgl/util/util.hpp | 15 +++++++ include/mbgl/util/uv.hpp | 12 ++++- include/mbgl/util/variant.hpp | 72 ++++++++++++++++++++--------- 4 files changed, 173 insertions(+), 21 deletions(-) create mode 100644 include/mbgl/util/async_queue.hpp create mode 100644 include/mbgl/util/util.hpp (limited to 'include/mbgl/util') diff --git a/include/mbgl/util/async_queue.hpp b/include/mbgl/util/async_queue.hpp new file mode 100644 index 0000000000..b3eaabc319 --- /dev/null +++ b/include/mbgl/util/async_queue.hpp @@ -0,0 +1,95 @@ +#ifndef MBGL_UTIL_ASYNC_QUEUE +#define MBGL_UTIL_ASYNC_QUEUE + +#include "std.hpp" + +#include + +#include +#include +#include +#include +#include + + +#if UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR <= 10 +#define UV_ASYNC_PARAMS(handle) uv_async_t *handle, int +#else +#define UV_ASYNC_PARAMS(handle) uv_async_t *handle +#endif + +namespace mbgl { +namespace util { + +template +class AsyncQueue { +public: + AsyncQueue(uv_loop_t *loop, std::function fn) : + callback(fn) { + async.data = this; + uv_async_init(loop, &async, [](UV_ASYNC_PARAMS(handle)) { + auto q = reinterpret_cast(handle->data); + q->process(); + }); + } + + void send(T &&data) { + { + std::lock_guard lock(mutex); + queue.push(util::make_unique(std::move(data))); + } + uv_async_send(&async); + } + + void send(std::unique_ptr data) { + { + std::lock_guard lock(mutex); + queue.push(std::move(data)); + } + uv_async_send(&async); + } + + void stop() { + uv_close((uv_handle_t *)&async, [](uv_handle_t *handle) { + delete reinterpret_cast(handle->data); + }); + } + + void ref() { + uv_ref((uv_handle_t *)&async); + } + + void unref() { + uv_unref((uv_handle_t *)&async); + } + +private: + ~AsyncQueue() { + } + + void process() { + std::unique_ptr item; + while (true) { + mutex.lock(); + if (queue.empty()) { + mutex.unlock(); + break; + } + item = std::move(queue.front()); + queue.pop(); + mutex.unlock(); + callback(*item); + } + } + +private: + std::mutex mutex; + uv_async_t async; + std::queue> queue; + std::function callback; +}; + +} +} + +#endif diff --git a/include/mbgl/util/util.hpp b/include/mbgl/util/util.hpp new file mode 100644 index 0000000000..bf5dad3c01 --- /dev/null +++ b/include/mbgl/util/util.hpp @@ -0,0 +1,15 @@ +#ifndef MBGL_UTIL_UTIL +#define MBGL_UTIL_UTIL + +#include + +#ifndef NDEBUG +#include +#define MBGL_STORE_THREAD(tid) const std::thread::id tid = std::this_thread::get_id(); +#define MBGL_VERIFY_THREAD(tid) assert(tid == std::this_thread::get_id()); +#else +#define MBGL_STORE_THREAD(tid) +#define MBGL_VERIFY_THREAD(tid) +#endif + +#endif diff --git a/include/mbgl/util/uv.hpp b/include/mbgl/util/uv.hpp index f59037c1d8..85f93e78bd 100644 --- a/include/mbgl/util/uv.hpp +++ b/include/mbgl/util/uv.hpp @@ -3,10 +3,11 @@ #include +typedef struct uv_handle_s uv_handle_t; typedef struct uv_async_s uv_async_t; typedef struct uv_timer_s uv_timer_t; -typedef struct uv_handle_s uv_handle_t; typedef struct uv_loop_s uv_loop_t; +typedef struct uv_fs_s uv_fs_t; namespace uv { @@ -19,6 +20,15 @@ class worker; class mutex; class cond; +const char *getFileRequestError(uv_fs_t *req); + +template +void close(T *specific) { + uv_close(reinterpret_cast(specific), [](uv_handle_t *generic) { + delete reinterpret_cast(generic); + }); +} + } #endif diff --git a/include/mbgl/util/variant.hpp b/include/mbgl/util/variant.hpp index 2de195cd69..411f1918d5 100644 --- a/include/mbgl/util/variant.hpp +++ b/include/mbgl/util/variant.hpp @@ -10,7 +10,7 @@ #include #include -#include +#include "recursive_wrapper.hpp" #ifdef _MSC_VER // http://msdn.microsoft.com/en-us/library/z8y1yy88.aspx @@ -34,7 +34,19 @@ // translates to 100 #define VARIANT_VERSION (VARIANT_MAJOR_VERSION*100000) + (VARIANT_MINOR_VERSION*100) + (VARIANT_PATCH_VERSION) -namespace mapbox { namespace util { namespace detail { +namespace mapbox { namespace util { + +// static visitor +template +struct static_visitor +{ + using result_type = R; +protected: + static_visitor() {} + ~static_visitor() {} +}; + +namespace detail { static constexpr std::size_t invalid_value = std::size_t(-1); @@ -109,18 +121,38 @@ struct select_type<0, T, Types...> using type = T; }; -} // namespace detail -// static visitor -template -struct static_visitor +template +struct enable_if_type { using type = R; }; + +template +struct result_of_unary_visit { - using result_type = R; -protected: - static_visitor() {} - ~static_visitor() {} + using type = typename std::result_of::type; }; +template +struct result_of_unary_visit::type > +{ + using type = typename F::result_type; +}; + +template +struct result_of_binary_visit +{ + using type = typename std::result_of::type; +}; + + +template +struct result_of_binary_visit::type > +{ + using type = typename F::result_type; +}; + + +} // namespace detail + template struct static_max; @@ -225,7 +257,7 @@ struct dispatcher; template struct dispatcher { - using result_type = typename F::result_type; + using result_type = typename detail::result_of_unary_visit::type; VARIANT_INLINE static result_type apply_const(V const& v, F f) { if (v.get_type_index() == sizeof...(Types)) @@ -254,7 +286,7 @@ struct dispatcher template struct dispatcher { - using result_type = typename F::result_type; + using result_type = typename detail::result_of_unary_visit::type; VARIANT_INLINE static result_type apply_const(V const&, F) { throw std::runtime_error(std::string("unary dispatch: FAIL ") + typeid(V).name()); @@ -273,7 +305,7 @@ struct binary_dispatcher_rhs; template struct binary_dispatcher_rhs { - using result_type = typename F::result_type; + using result_type = typename detail::result_of_binary_visit::type; VARIANT_INLINE static result_type apply_const(V const& lhs, V const& rhs, F f) { if (rhs.get_type_index() == sizeof...(Types)) // call binary functor @@ -305,7 +337,7 @@ struct binary_dispatcher_rhs template struct binary_dispatcher_rhs { - using result_type = typename F::result_type; + using result_type = typename detail::result_of_binary_visit::type; VARIANT_INLINE static result_type apply_const(V const&, V const&, F) { throw std::runtime_error("binary dispatch: FAIL"); @@ -323,7 +355,7 @@ struct binary_dispatcher_lhs; template struct binary_dispatcher_lhs { - using result_type = typename F::result_type; + using result_type = typename detail::result_of_binary_visit::type; VARIANT_INLINE static result_type apply_const(V const& lhs, V const& rhs, F f) { if (lhs.get_type_index() == sizeof...(Types)) // call binary functor @@ -353,7 +385,7 @@ struct binary_dispatcher_lhs template struct binary_dispatcher_lhs { - using result_type = typename F::result_type; + using result_type = typename detail::result_of_binary_visit::type; VARIANT_INLINE static result_type apply_const(V const&, V const&, F) { throw std::runtime_error("binary dispatch: FAIL"); @@ -371,7 +403,7 @@ struct binary_dispatcher; template struct binary_dispatcher { - using result_type = typename F::result_type; + using result_type = typename detail::result_of_binary_visit::type; VARIANT_INLINE static result_type apply_const(V const& v0, V const& v1, F f) { if (v0.get_type_index() == sizeof...(Types)) @@ -416,7 +448,7 @@ struct binary_dispatcher template struct binary_dispatcher { - using result_type = typename F::result_type; + using result_type = typename detail::result_of_binary_visit::type; VARIANT_INLINE static result_type apply_const(V const&, V const&, F) { throw std::runtime_error("binary dispatch: FAIL"); @@ -448,7 +480,7 @@ struct less_comp }; template -class comparer : public static_visitor +class comparer { public: explicit comparer(Variant const& lhs) noexcept @@ -467,7 +499,7 @@ private: // operator<< helper template -class printer : public static_visitor<> +class printer { public: explicit printer(Out & out) -- cgit v1.2.1