diff options
author | John Firebaugh <john.firebaugh@gmail.com> | 2016-02-16 12:52:25 -0800 |
---|---|---|
committer | John Firebaugh <john.firebaugh@gmail.com> | 2016-04-01 09:26:54 -0700 |
commit | 879382f72405edd1840d2f37744bcba49131859a (patch) | |
tree | 4f632c8973d1c5539437e790edb471090339b533 /platform/darwin | |
parent | 7e9a4f15c5082dfe5987e1dcbb4b816f04068a60 (diff) | |
download | qtlocation-mapboxgl-879382f72405edd1840d2f37744bcba49131859a.tar.gz |
[ios, osx] Replace libuv with native implementations
Diffstat (limited to 'platform/darwin')
-rw-r--r-- | platform/darwin/src/async_task.cpp | 71 | ||||
-rw-r--r-- | platform/darwin/src/run_loop.cpp | 51 | ||||
-rw-r--r-- | platform/darwin/src/timer.cpp | 60 |
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 |