diff options
author | Konstantin Käfer <mail@kkaefer.com> | 2014-03-01 13:05:13 +0100 |
---|---|---|
committer | Konstantin Käfer <mail@kkaefer.com> | 2014-03-01 13:05:13 +0100 |
commit | 6c58101b12ee8e599aff3541f10c1fbfe5a027fb (patch) | |
tree | 190fd66b912ab47956fd547237056a9ee1ecdbbe /linux/main.cpp | |
parent | 0782cfc5be92ebc79711f6f9756db303026030e3 (diff) | |
download | qtlocation-mapboxgl-6c58101b12ee8e599aff3541f10c1fbfe5a027fb.tar.gz |
multithreaded curl for linux
Diffstat (limited to 'linux/main.cpp')
-rw-r--r-- | linux/main.cpp | 98 |
1 files changed, 67 insertions, 31 deletions
diff --git a/linux/main.cpp b/linux/main.cpp index 1e6c409a0f..328027414e 100644 --- a/linux/main.cpp +++ b/linux/main.cpp @@ -5,15 +5,28 @@ #include "settings.hpp" #include <future> #include <list> +#include <forward_list> #include <chrono> -#include <thread> +#include <pthread.h> + +namespace llmr { +namespace platform { + +struct Request { + pthread_t thread; + pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + std::string url; + bool done = false; + std::function<void(Response&)> background_function; + std::function<void()> foreground_callback; +}; + +} +} + +std::forward_list<llmr::platform::Request *> requests; -std::list<std::future<void>> futures; -std::list<std::future<void>>::iterator f_it; -std::list<std::function<void()>> callbacks; -std::list<std::function<void()>>::iterator c_it; -std::chrono::milliseconds zero (0); class MapView { public: @@ -159,21 +172,22 @@ public: int run() { while (!glfwWindowShouldClose(window)) { - - f_it = futures.begin(); - c_it = callbacks.begin(); - - while (f_it != futures.end()) { - if (f_it->wait_for(zero) == std::future_status::ready) { - std::function<void()> cb = *c_it; - futures.erase(f_it++); - callbacks.erase(c_it++); - cb(); + bool& dirty = this->dirty; + requests.remove_if([&dirty](llmr::platform::Request *req) { + pthread_mutex_lock(&req->mutex); + if (req->done) { + pthread_mutex_unlock(&req->mutex); + req->foreground_callback(); + pthread_join(req->thread, nullptr); + pthread_mutex_destroy(&req->mutex); + delete req; + dirty = true; + return true; } else { - f_it++; - c_it++; + pthread_mutex_unlock(&req->mutex); + return false; } - } + }); if (dirty) { try { @@ -185,7 +199,7 @@ public: fps(); } - if (dirty || futures.size()) { + if (!requests.empty() || dirty) { glfwPollEvents(); } else { glfwWaitEvents(); @@ -237,29 +251,29 @@ MapView *mapView = nullptr; namespace llmr { namespace platform { -void restart(void *) { +void restart() { if (mapView) { mapView->dirty = true; } } - - static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp) { - ((std::string*)userp)->append((char*)contents, size *nmemb); + ((std::string *)userp)->append((char *)contents, size * nmemb); return size * nmemb; } -void request_http_async(std::string url, std::function<void(Response&)> func) { - +void *request_http(void *ptr) { + Request *req = static_cast<Request *>(ptr); Response res; + // TODO: use curl multi to be able to cancel + CURL *curl; CURLcode code; curl = curl_easy_init(); if (curl) { - curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + curl_easy_setopt(curl, CURLOPT_URL, req->url.c_str()); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); curl_easy_setopt(curl, CURLOPT_WRITEDATA, &res.body); curl_easy_setopt(curl, CURLOPT_ACCEPT_ENCODING, "deflate"); @@ -268,14 +282,33 @@ void request_http_async(std::string url, std::function<void(Response&)> func) { curl_easy_cleanup(curl); } - func(res); + req->background_function(res); + + pthread_mutex_lock(&req->mutex); + req->done = true; + pthread_mutex_unlock(&req->mutex); + + pthread_exit(nullptr); } -void request_http(std::string url, std::function<void(Response&)> func, std::function<void()> cb) { - futures.emplace_back(std::async(std::launch::async, request_http_async, url, func)); - callbacks.push_back(cb); +Request *request_http(std::string url, std::function<void(Response&)> background_function, std::function<void()> foreground_callback) { + Request *req = new Request(); + req->url = url; + req->background_function = background_function; + req->foreground_callback = foreground_callback; + requests.push_front(req); + int rc = pthread_create(&req->thread, nullptr, request_http, (void *)req); + if (rc) { + fprintf(stderr, "http request failed\n"); + return nullptr; + } + + return req; } +void cancel_request_http(Request *request) { + fprintf(stderr, "cancel %p\n", request); +} double time() { return glfwGetTime(); @@ -285,10 +318,13 @@ double time() { } int main() { + curl_global_init(CURL_GLOBAL_ALL); + mapView = new MapView(); mapView->init(); int ret = mapView->run(); mapView->settings.sync(); delete mapView; + pthread_exit(NULL); return ret; } |