summaryrefslogtreecommitdiff
path: root/platform/darwin
diff options
context:
space:
mode:
authorJohn Firebaugh <john.firebaugh@gmail.com>2016-02-16 12:52:25 -0800
committerJohn Firebaugh <john.firebaugh@gmail.com>2016-04-01 09:26:54 -0700
commit879382f72405edd1840d2f37744bcba49131859a (patch)
tree4f632c8973d1c5539437e790edb471090339b533 /platform/darwin
parent7e9a4f15c5082dfe5987e1dcbb4b816f04068a60 (diff)
downloadqtlocation-mapboxgl-879382f72405edd1840d2f37744bcba49131859a.tar.gz
[ios, osx] Replace libuv with native implementations
Diffstat (limited to 'platform/darwin')
-rw-r--r--platform/darwin/src/async_task.cpp71
-rw-r--r--platform/darwin/src/run_loop.cpp51
-rw-r--r--platform/darwin/src/timer.cpp60
3 files changed, 182 insertions, 0 deletions
diff --git a/platform/darwin/src/async_task.cpp b/platform/darwin/src/async_task.cpp
new file mode 100644
index 0000000000..122f95f738
--- /dev/null
+++ b/platform/darwin/src/async_task.cpp
@@ -0,0 +1,71 @@
+#include <mbgl/util/async_task.hpp>
+
+#include <CoreFoundation/CoreFoundation.h>
+
+#include <atomic>
+
+namespace mbgl {
+namespace util {
+
+class AsyncTask::Impl {
+public:
+ Impl(std::function<void()>&& fn)
+ : task(std::move(fn)),
+ loop(CFRunLoopGetCurrent()) {
+ CFRunLoopSourceContext context = {
+ 0,
+ this,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ nullptr,
+ perform
+ };
+ source = CFRunLoopSourceCreate(kCFAllocatorDefault, 0, &context);
+ CFRunLoopAddSource(loop, source, kCFRunLoopDefaultMode);
+ }
+
+ ~Impl() {
+ CFRunLoopRemoveSource(loop, source, kCFRunLoopDefaultMode);
+ CFRelease(source);
+ }
+
+ void maySend() {
+ if (!queued.test_and_set()) {
+ CFRunLoopSourceSignal(source);
+ CFRunLoopWakeUp(loop);
+ }
+ }
+
+ void runTask() {
+ queued.clear();
+ task();
+ }
+
+private:
+ static void perform(void* info) {
+ reinterpret_cast<Impl*>(info)->runTask();
+ }
+
+ std::function<void()> task;
+ std::atomic_flag queued = ATOMIC_FLAG_INIT;
+
+ CFRunLoopRef loop;
+ CFRunLoopSourceRef source;
+};
+
+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
diff --git a/platform/darwin/src/run_loop.cpp b/platform/darwin/src/run_loop.cpp
new file mode 100644
index 0000000000..6e9a1c50b0
--- /dev/null
+++ b/platform/darwin/src/run_loop.cpp
@@ -0,0 +1,51 @@
+#include <mbgl/util/run_loop.hpp>
+#include <mbgl/util/async_task.hpp>
+#include <mbgl/util/thread_local.hpp>
+
+#include <CoreFoundation/CoreFoundation.h>
+
+namespace mbgl {
+namespace util {
+
+static ThreadLocal<RunLoop>& current = *new ThreadLocal<RunLoop>;
+static RunLoop mainRunLoop;
+
+class RunLoop::Impl {
+public:
+ std::unique_ptr<AsyncTask> async;
+};
+
+RunLoop* RunLoop::Get() {
+ assert(current.get());
+ return current.get();
+}
+
+RunLoop::RunLoop(Type)
+ : impl(std::make_unique<Impl>()) {
+ current.set(this);
+ impl->async = std::make_unique<AsyncTask>(std::bind(&RunLoop::process, this));
+}
+
+RunLoop::~RunLoop() {
+ current.set(nullptr);
+}
+
+void RunLoop::push(std::shared_ptr<WorkTask> task) {
+ withMutex([&] { queue.push(std::move(task)); });
+ impl->async->send();
+}
+
+void RunLoop::run() {
+ CFRunLoopRun();
+}
+
+void RunLoop::runOnce() {
+ CFRunLoopRunInMode(kCFRunLoopDefaultMode, 0, false);
+}
+
+void RunLoop::stop() {
+ invoke([&] { CFRunLoopStop(CFRunLoopGetCurrent()); });
+}
+
+} // namespace util
+} // namespace mbgl
diff --git a/platform/darwin/src/timer.cpp b/platform/darwin/src/timer.cpp
new file mode 100644
index 0000000000..e9e58d86c6
--- /dev/null
+++ b/platform/darwin/src/timer.cpp
@@ -0,0 +1,60 @@
+#include <mbgl/util/timer.hpp>
+
+#include <CoreFoundation/CoreFoundation.h>
+
+namespace mbgl {
+namespace util {
+
+CFTimeInterval toCFTimeInterval(Duration duration) {
+ return std::chrono::duration<CFTimeInterval>(duration).count();
+}
+
+CFAbsoluteTime toCFAbsoluteTime(Duration duration) {
+ return CFAbsoluteTimeGetCurrent() + toCFTimeInterval(duration);
+}
+
+class Timer::Impl {
+public:
+ Impl(Duration timeout, Duration repeat, std::function<void()>&& fn)
+ : task(std::move(fn)),
+ loop(CFRunLoopGetCurrent()) {
+ CFRunLoopTimerContext context = {
+ 0,
+ this,
+ nullptr,
+ nullptr,
+ nullptr
+ };
+ timer = CFRunLoopTimerCreate(kCFAllocatorDefault, toCFAbsoluteTime(timeout), toCFTimeInterval(repeat), 0, 0, perform, &context);
+ CFRunLoopAddTimer(loop, timer, kCFRunLoopDefaultMode);
+ }
+
+ ~Impl() {
+ CFRunLoopRemoveTimer(loop, timer, kCFRunLoopDefaultMode);
+ CFRelease(timer);
+ }
+
+private:
+ static void perform(CFRunLoopTimerRef, void* info) {
+ reinterpret_cast<Impl*>(info)->task();
+ }
+
+ std::function<void()> task;
+
+ CFRunLoopRef loop;
+ CFRunLoopTimerRef timer;
+};
+
+Timer::Timer() = default;
+Timer::~Timer() = default;
+
+void Timer::start(Duration timeout, Duration repeat, std::function<void()>&& cb) {
+ impl = std::make_unique<Impl>(timeout, repeat, std::move(cb));
+}
+
+void Timer::stop() {
+ impl.reset();
+}
+
+} // namespace util
+} // namespace mbgl