summaryrefslogtreecommitdiff
path: root/platform/default/src/mbgl/util/async_task.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'platform/default/src/mbgl/util/async_task.cpp')
-rw-r--r--platform/default/src/mbgl/util/async_task.cpp66
1 files changed, 66 insertions, 0 deletions
diff --git a/platform/default/src/mbgl/util/async_task.cpp b/platform/default/src/mbgl/util/async_task.cpp
new file mode 100644
index 0000000000..50891056d8
--- /dev/null
+++ b/platform/default/src/mbgl/util/async_task.cpp
@@ -0,0 +1,66 @@
+#include <mbgl/util/async_task.hpp>
+
+#include <mbgl/util/run_loop.hpp>
+
+#include <atomic>
+#include <functional>
+
+#include <uv.h>
+
+namespace mbgl {
+namespace util {
+
+class AsyncTask::Impl {
+public:
+ Impl(std::function<void()>&& fn)
+ : async(new uv_async_t),
+ task(std::move(fn)) {
+
+ auto* loop = reinterpret_cast<uv_loop_t*>(RunLoop::getLoopHandle());
+ if (uv_async_init(loop, async, asyncCallback) != 0) {
+ throw std::runtime_error("Failed to initialize async.");
+ }
+
+ handle()->data = this;
+ uv_unref(handle());
+ }
+
+ ~Impl() {
+ uv_close(handle(), [](uv_handle_t* h) {
+ delete reinterpret_cast<uv_async_t*>(h);
+ });
+ }
+
+ void maySend() {
+ // uv_async_send will do the call coalescing for us.
+ if (uv_async_send(async) != 0) {
+ throw std::runtime_error("Failed to async send.");
+ }
+ }
+
+private:
+ static void asyncCallback(uv_async_t* handle) {
+ reinterpret_cast<Impl*>(handle->data)->task();
+ }
+
+ uv_handle_t* handle() {
+ return reinterpret_cast<uv_handle_t*>(async);
+ }
+
+ uv_async_t* async;
+
+ std::function<void()> task;
+};
+
+AsyncTask::AsyncTask(std::function<void()>&& fn)
+ : impl(std::make_unique<Impl>(std::move(fn))) {
+}
+
+AsyncTask::~AsyncTask() = default;
+
+void AsyncTask::send() {
+ impl->maySend();
+}
+
+} // namespace util
+} // namespace mbgl