diff options
author | Thiago Marcos P. Santos <thiago@mapbox.com> | 2015-11-20 16:01:35 +0200 |
---|---|---|
committer | Thiago Marcos P. Santos <thiago@mapbox.com> | 2015-12-01 11:49:02 +0200 |
commit | 07c0424ab95a5e6b963c6a2f387adb9f2aa26c9b (patch) | |
tree | e21cee7404c1c90e927ddec131c8eb573046d215 /platform/default/run_loop.cpp | |
parent | a1f714bd373b1ab2836e69321944746b72fe1e37 (diff) | |
download | qtlocation-mapboxgl-07c0424ab95a5e6b963c6a2f387adb9f2aa26c9b.tar.gz |
[core] Removed libuv dependency from HTTPCurl*
Moved the fd watcher to the RunLoop. So far only needs to
be implemented by platforms using HTTPCurlRequest et al.
Diffstat (limited to 'platform/default/run_loop.cpp')
-rw-r--r-- | platform/default/run_loop.cpp | 106 |
1 files changed, 106 insertions, 0 deletions
diff --git a/platform/default/run_loop.cpp b/platform/default/run_loop.cpp index 845ee1b2ab..9ca7cc9207 100644 --- a/platform/default/run_loop.cpp +++ b/platform/default/run_loop.cpp @@ -3,6 +3,9 @@ #include <mbgl/util/uv.hpp> #include <mbgl/util/thread_local.hpp> +#include <functional> +#include <unordered_map> + namespace { using namespace mbgl::util; @@ -13,6 +16,38 @@ static ThreadLocal<RunLoop>& current = *new ThreadLocal<RunLoop>; namespace mbgl { namespace util { +struct Watch { + static void onEvent(uv_poll_t* poll, int, int event) { + auto watch = reinterpret_cast<Watch*>(poll->data); + + RunLoop::Event watchEvent = RunLoop::Event::None; + switch (event) { + case UV_READABLE: + watchEvent = RunLoop::Event::Read; + break; + case UV_WRITABLE: + watchEvent = RunLoop::Event::Write; + break; + case UV_READABLE | UV_WRITABLE: + watchEvent = RunLoop::Event::ReadWrite; + break; + } + + watch->eventCallback(watch->fd, watchEvent); + }; + + static void onClose(uv_handle_t *poll) { + auto watch = reinterpret_cast<Watch*>(poll->data); + watch->closeCallback(); + }; + + uv_poll_t poll; + int fd; + + std::function<void(int, RunLoop::Event)> eventCallback; + std::function<void()> closeCallback; +}; + RunLoop* RunLoop::Get() { return current.get(); } @@ -24,6 +59,8 @@ public: uv_loop_t *loop; RunLoop::Type type; std::unique_ptr<AsyncTask> async; + + std::unordered_map<int, std::unique_ptr<Watch>> watchPoll; }; RunLoop::RunLoop(Type type) : impl(std::make_unique<Impl>()) { @@ -84,10 +121,14 @@ void RunLoop::push(std::shared_ptr<WorkTask> task) { } void RunLoop::run() { + MBGL_VERIFY_THREAD(tid); + uv_run(impl->loop, UV_RUN_DEFAULT); } void RunLoop::runOnce() { + MBGL_VERIFY_THREAD(tid); + uv_run(impl->loop, UV_RUN_ONCE); } @@ -95,5 +136,70 @@ void RunLoop::stop() { invoke([&] { impl->async->unref(); }); } +void RunLoop::addWatch(int fd, Event event, std::function<void(int, Event)>&& callback) { + MBGL_VERIFY_THREAD(tid); + + Watch *watch = nullptr; + auto watchPollIter = impl->watchPoll.find(fd); + + if (watchPollIter == impl->watchPoll.end()) { + std::unique_ptr<Watch> watchPtr = std::make_unique<Watch>(); + + watch = watchPtr.get(); + impl->watchPoll[fd] = std::move(watchPtr); + + if (uv_poll_init(impl->loop, &watch->poll, fd)) { + throw std::runtime_error("Failed to init poll on file descriptor."); + } + } else { + watch = watchPollIter->second.get(); + } + + watch->poll.data = watch; + watch->fd = fd; + watch->eventCallback = std::move(callback); + + int pollEvent = 0; + switch (event) { + case Event::Read: + pollEvent = UV_READABLE; + break; + case Event::Write: + pollEvent = UV_WRITABLE; + break; + case Event::ReadWrite: + pollEvent = UV_READABLE | UV_WRITABLE; + break; + default: + throw std::runtime_error("Unhandled event."); + } + + if (uv_poll_start(&watch->poll, pollEvent, &Watch::onEvent)) { + throw std::runtime_error("Failed to start poll on file descriptor."); + } +} + +void RunLoop::removeWatch(int fd) { + MBGL_VERIFY_THREAD(tid); + + auto watchPollIter = impl->watchPoll.find(fd); + if (watchPollIter == impl->watchPoll.end()) { + return; + } + + Watch* watch = watchPollIter->second.release(); + impl->watchPoll.erase(watchPollIter); + + watch->closeCallback = [watch] { + delete watch; + }; + + if (uv_poll_stop(&watch->poll)) { + throw std::runtime_error("Failed to stop poll on file descriptor."); + } + + uv_close(reinterpret_cast<uv_handle_t*>(&watch->poll), &Watch::onClose); +} + } } |