diff options
-rw-r--r-- | gyp/platform-android.gypi | 1 | ||||
-rw-r--r-- | gyp/platform-ios.gypi | 1 | ||||
-rw-r--r-- | gyp/platform-linux.gypi | 1 | ||||
-rw-r--r-- | gyp/platform-osx.gypi | 1 | ||||
-rw-r--r-- | include/mbgl/util/run_loop.hpp | 45 | ||||
-rw-r--r-- | platform/default/async_task.cpp | 2 | ||||
-rw-r--r-- | platform/default/run_loop.cpp | 83 | ||||
-rw-r--r-- | platform/node/src/node_mapbox_gl_native.cpp | 2 | ||||
-rw-r--r-- | src/mbgl/storage/default_file_source.cpp | 2 | ||||
-rw-r--r-- | src/mbgl/util/run_loop.cpp | 37 | ||||
-rw-r--r-- | src/mbgl/util/thread.hpp | 23 |
11 files changed, 131 insertions, 67 deletions
diff --git a/gyp/platform-android.gypi b/gyp/platform-android.gypi index dcab0e0193..02f46b0636 100644 --- a/gyp/platform-android.gypi +++ b/gyp/platform-android.gypi @@ -13,6 +13,7 @@ '../platform/android/log_android.cpp', '../platform/android/asset_root.cpp', '../platform/default/async_task.cpp', + '../platform/default/run_loop.cpp', '../platform/default/thread.cpp', '../platform/default/string_stdlib.cpp', '../platform/default/image.cpp', diff --git a/gyp/platform-ios.gypi b/gyp/platform-ios.gypi index 0b23890c42..240fa28e41 100644 --- a/gyp/platform-ios.gypi +++ b/gyp/platform-ios.gypi @@ -11,6 +11,7 @@ 'sources': [ '../platform/default/async_task.cpp', + '../platform/default/run_loop.cpp', '../platform/darwin/log_nslog.mm', '../platform/darwin/string_nsstring.mm', '../platform/darwin/application_root.mm', diff --git a/gyp/platform-linux.gypi b/gyp/platform-linux.gypi index 1ba328c5cc..ce2fe3b147 100644 --- a/gyp/platform-linux.gypi +++ b/gyp/platform-linux.gypi @@ -13,6 +13,7 @@ '../platform/default/async_task.cpp', '../platform/default/log_stderr.cpp', '../platform/default/string_stdlib.cpp', + '../platform/default/run_loop.cpp', '../platform/default/application_root.cpp', '../platform/default/asset_root.cpp', '../platform/default/thread.cpp', diff --git a/gyp/platform-osx.gypi b/gyp/platform-osx.gypi index b3941d2e2d..a410826b51 100644 --- a/gyp/platform-osx.gypi +++ b/gyp/platform-osx.gypi @@ -11,6 +11,7 @@ 'sources': [ '../platform/default/async_task.cpp', + '../platform/default/run_loop.cpp', '../platform/darwin/log_nslog.mm', '../platform/darwin/string_nsstring.mm', '../platform/darwin/application_root.mm', diff --git a/include/mbgl/util/run_loop.hpp b/include/mbgl/util/run_loop.hpp index 6113ac2215..4b98653556 100644 --- a/include/mbgl/util/run_loop.hpp +++ b/include/mbgl/util/run_loop.hpp @@ -1,6 +1,7 @@ #ifndef MBGL_UTIL_RUN_LOOP #define MBGL_UTIL_RUN_LOOP +#include <mbgl/util/async_task.hpp> #include <mbgl/util/noncopyable.hpp> #include <mbgl/util/work_task.hpp> #include <mbgl/util/work_request.hpp> @@ -15,19 +16,26 @@ namespace mbgl { namespace util { +typedef void * LOOP_HANDLE; + class RunLoop : private util::noncopyable { public: - RunLoop(uv_loop_t*); + enum class Type : uint8_t { + Default, + New, + }; + + RunLoop(Type type = Type::Default); ~RunLoop(); static RunLoop* Get() { return current.get(); } - static uv_loop_t* getLoop() { - return current.get()->get(); - } + static LOOP_HANDLE getLoopHandle(); + void run(); + void runOnce(); void stop(); // Invoke fn(args...) on this RunLoop. @@ -39,7 +47,7 @@ public: std::move(tuple)); withMutex([&] { queue.push(task); }); - async.send(); + async->send(); } // Post the cancellable work fn(args...) to this RunLoop. @@ -56,7 +64,7 @@ public: flag); withMutex([&] { queue.push(task); }); - async.send(); + async->send(); return std::make_unique<WorkRequest>(task); } @@ -90,13 +98,11 @@ public: flag); withMutex([&] { queue.push(task); }); - async.send(); + async->send(); return std::make_unique<WorkRequest>(task); } - uv_loop_t* get() { return async.get()->loop; } - private: template <class F, class P> class Invoker : public WorkTask { @@ -143,12 +149,27 @@ private: using Queue = std::queue<std::shared_ptr<WorkTask>>; - void withMutex(std::function<void()>&&); - void process(); + void withMutex(std::function<void()>&& fn) { + std::lock_guard<std::mutex> lock(mutex); + fn(); + } + + void process() { + Queue queue_; + withMutex([&] { queue_.swap(queue); }); + + while (!queue_.empty()) { + (*(queue_.front()))(); + queue_.pop(); + } + } Queue queue; std::mutex mutex; - uv::async async; + std::unique_ptr<AsyncTask> async; + + class Impl; + std::unique_ptr<Impl> impl; static uv::tls<RunLoop> current; }; diff --git a/platform/default/async_task.cpp b/platform/default/async_task.cpp index 4b4372451c..1f2381f716 100644 --- a/platform/default/async_task.cpp +++ b/platform/default/async_task.cpp @@ -12,7 +12,7 @@ namespace util { class AsyncTask::Impl { public: Impl(std::function<void()>&& fn) - : async(RunLoop::getLoop(), [this] { runTask(); }) + : async(reinterpret_cast<uv_loop_t*>(RunLoop::getLoopHandle()), [this] { runTask(); }) , task(std::move(fn)) { } diff --git a/platform/default/run_loop.cpp b/platform/default/run_loop.cpp new file mode 100644 index 0000000000..7c3a74f2cb --- /dev/null +++ b/platform/default/run_loop.cpp @@ -0,0 +1,83 @@ +#include <mbgl/util/run_loop.hpp> + +#include <uv.h> + +namespace mbgl { +namespace util { + +uv::tls<RunLoop> RunLoop::current; + +class RunLoop::Impl { +public: + Impl() = default; + + uv_loop_t *loop; + RunLoop::Type type; +}; + +RunLoop::RunLoop(Type type) : impl(std::make_unique<Impl>()) { + switch (type) { + case Type::New: +#if UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR <= 10 + impl->loop = uv_loop_new(); + if (impl->loop == nullptr) { +#else + impl->loop = new uv_loop_t; + if (uv_loop_init(impl->loop) != 0) { +#endif + throw std::runtime_error("Failed to initialize loop."); + } + break; + case Type::Default: + impl->loop = uv_default_loop(); + break; + } + + impl->type = type; + + current.set(this); + async = std::make_unique<AsyncTask>(std::bind(&RunLoop::process, this)); +} + +RunLoop::~RunLoop() { + current.set(nullptr); + + if (impl->type == Type::Default) { + return; + } + + // Run the loop again to ensure that async + // close callbacks have been called. Not needed + // for the default main loop because it is only + // closed when the application exits. + async.reset(); + runOnce(); + +#if UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR <= 10 + uv_loop_delete(impl->loop); +#else + if (uv_loop_close(impl->loop) == UV_EBUSY) { + throw std::runtime_error("Failed to close loop."); + } + delete impl->loop; +#endif +} + +LOOP_HANDLE RunLoop::getLoopHandle() { + return current.get()->impl->loop; +} + +void RunLoop::run() { + uv_run(impl->loop, UV_RUN_DEFAULT); +} + +void RunLoop::runOnce() { + uv_run(impl->loop, UV_RUN_ONCE); +} + +void RunLoop::stop() { + invoke([&] { async->unref(); }); +} + +} +} diff --git a/platform/node/src/node_mapbox_gl_native.cpp b/platform/node/src/node_mapbox_gl_native.cpp index 4a86a8d855..e0b094d570 100644 --- a/platform/node/src/node_mapbox_gl_native.cpp +++ b/platform/node/src/node_mapbox_gl_native.cpp @@ -13,7 +13,7 @@ namespace node_mbgl { mbgl::util::RunLoop& NodeRunLoop() { - static mbgl::util::RunLoop nodeRunLoop(uv_default_loop()); + static mbgl::util::RunLoop nodeRunLoop; return nodeRunLoop; } diff --git a/src/mbgl/storage/default_file_source.cpp b/src/mbgl/storage/default_file_source.cpp index 9e2289102e..439acd8888 100644 --- a/src/mbgl/storage/default_file_source.cpp +++ b/src/mbgl/storage/default_file_source.cpp @@ -78,7 +78,7 @@ void DefaultFileSource::cancel(const Resource& res, FileRequest* req) { // ----- Impl ----- DefaultFileSource::Impl::Impl(FileCache* cache_, const std::string& root) - : loop(util::RunLoop::getLoop()), + : loop(reinterpret_cast<uv_loop_t*>(util::RunLoop::getLoopHandle())), cache(cache_), assetRoot(root.empty() ? platform::assetRoot() : root), assetContext(AssetContextBase::createContext(loop)), diff --git a/src/mbgl/util/run_loop.cpp b/src/mbgl/util/run_loop.cpp deleted file mode 100644 index 7f277c9885..0000000000 --- a/src/mbgl/util/run_loop.cpp +++ /dev/null @@ -1,37 +0,0 @@ -#include <mbgl/util/run_loop.hpp> - -namespace mbgl { -namespace util { - -uv::tls<RunLoop> RunLoop::current; - -RunLoop::RunLoop(uv_loop_t* loop) - : async(loop, std::bind(&RunLoop::process, this)) { - current.set(this); -} - -RunLoop::~RunLoop() { - current.set(nullptr); -} - -void RunLoop::withMutex(std::function<void()>&& fn) { - std::lock_guard<std::mutex> lock(mutex); - fn(); -} - -void RunLoop::process() { - Queue queue_; - withMutex([&] { queue_.swap(queue); }); - - while (!queue_.empty()) { - (*(queue_.front()))(); - queue_.pop(); - } -} - -void RunLoop::stop() { - invoke([&] { async.unref(); }); -} - -} -} diff --git a/src/mbgl/util/thread.hpp b/src/mbgl/util/thread.hpp index d7611254cc..7924d3d4cf 100644 --- a/src/mbgl/util/thread.hpp +++ b/src/mbgl/util/thread.hpp @@ -112,26 +112,19 @@ Thread<Object>::Thread(const ThreadContext& context, Args&&... args) { template <class Object> template <typename P, std::size_t... I> void Thread<Object>::run(ThreadContext context, P&& params, std::index_sequence<I...>) { - uv::loop l; - ThreadContext::current.set(&context); - { - RunLoop loop_(l.get()); - loop = &loop_; - - Object object_(std::get<I>(std::forward<P>(params))...); - object = &object_; + RunLoop loop_(RunLoop::Type::New); + loop = &loop_; - running.set_value(); - l.run(); + Object object_(std::get<I>(std::forward<P>(params))...); + object = &object_; - loop = nullptr; - object = nullptr; - } + running.set_value(); + loop_.run(); - // Run the loop again to ensure that async close callbacks have been called. - l.run(); + loop = nullptr; + object = nullptr; ThreadContext::current.set(nullptr); |