summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gyp/platform-android.gypi1
-rw-r--r--gyp/platform-ios.gypi1
-rw-r--r--gyp/platform-linux.gypi1
-rw-r--r--gyp/platform-osx.gypi1
-rw-r--r--include/mbgl/util/run_loop.hpp45
-rw-r--r--platform/default/async_task.cpp2
-rw-r--r--platform/default/run_loop.cpp83
-rw-r--r--platform/node/src/node_mapbox_gl_native.cpp2
-rw-r--r--src/mbgl/storage/default_file_source.cpp2
-rw-r--r--src/mbgl/util/run_loop.cpp37
-rw-r--r--src/mbgl/util/thread.hpp23
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);