summaryrefslogtreecommitdiff
path: root/platform/default/run_loop.cpp
diff options
context:
space:
mode:
authorThiago Marcos P. Santos <thiago@mapbox.com>2015-11-20 16:01:35 +0200
committerThiago Marcos P. Santos <thiago@mapbox.com>2015-12-01 11:49:02 +0200
commit07c0424ab95a5e6b963c6a2f387adb9f2aa26c9b (patch)
treee21cee7404c1c90e927ddec131c8eb573046d215 /platform/default/run_loop.cpp
parenta1f714bd373b1ab2836e69321944746b72fe1e37 (diff)
downloadqtlocation-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.cpp106
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);
+}
+
}
}