summaryrefslogtreecommitdiff
path: root/linux
diff options
context:
space:
mode:
authorKonstantin Käfer <mail@kkaefer.com>2014-03-01 13:05:13 +0100
committerKonstantin Käfer <mail@kkaefer.com>2014-03-01 13:05:13 +0100
commit6c58101b12ee8e599aff3541f10c1fbfe5a027fb (patch)
tree190fd66b912ab47956fd547237056a9ee1ecdbbe /linux
parent0782cfc5be92ebc79711f6f9756db303026030e3 (diff)
downloadqtlocation-mapboxgl-6c58101b12ee8e599aff3541f10c1fbfe5a027fb.tar.gz
multithreaded curl for linux
Diffstat (limited to 'linux')
-rw-r--r--linux/llmr-app.gyp56
-rw-r--r--linux/main.cpp98
2 files changed, 113 insertions, 41 deletions
diff --git a/linux/llmr-app.gyp b/linux/llmr-app.gyp
index 06d7ed822e..79c1d4560d 100644
--- a/linux/llmr-app.gyp
+++ b/linux/llmr-app.gyp
@@ -13,16 +13,52 @@
"./settings.cpp",
"./settings.hpp"
],
- 'product_extension': 'app',
- 'link_settings': {
- 'libraries': [
- '<@(glfw3_libraries)',
- '-lcurl'
- ],
- },
- 'cflags': [
- '<@(png_cflags)',
- '<@(glfw3_cflags)'
+ 'conditions': [
+ ['OS == "mac"', {
+ 'product_extension': 'app',
+ 'mac_bundle_resources': [
+ 'Icon.icns',
+ ],
+ 'link_settings': {
+ 'libraries': [
+ '$(SDKROOT)/System/Library/Frameworks/Cocoa.framework',
+ '$(SDKROOT)/System/Library/Frameworks/IOKit.framework',
+ '$(SDKROOT)/System/Library/Frameworks/OpenGL.framework',
+ '$(SDKROOT)/System/Library/Frameworks/CoreVideo.framework',
+ ],
+ },
+ 'xcode_settings': {
+ 'ARCHS': [ "x86_64" ],
+ 'SDKROOT': 'macosx',
+ 'SUPPORTED_PLATFORMS':'macosx',
+ 'OTHER_CPLUSPLUSFLAGS':[
+ '<@(glfw3_cflags)'
+ ],
+ 'OTHER_LDFLAGS': [
+ '-stdlib=libc++',
+ '<@(glfw3_libraries)',
+ '-lcurl',
+ ],
+ 'SDKROOT': 'macosx',
+ 'INFOPLIST_FILE': 'Info.plist',
+ 'CLANG_CXX_LIBRARY': 'libc++',
+ 'CLANG_CXX_LANGUAGE_STANDARD':'c++11',
+ 'MACOSX_DEPLOYMENT_TARGET':'10.9',
+ 'GCC_VERSION': 'com.apple.compilers.llvm.clang.1_0',
+ 'CLANG_ENABLE_OBJC_ARC': 'YES'
+ },
+ }, {
+ 'link_settings': {
+ 'libraries': [
+ '<@(glfw3_libraries)',
+ '-lcurl'
+ ],
+ },
+ 'cflags': [
+ '<@(png_cflags)',
+ '<@(glfw3_cflags)'
+ ],
+ }]
],
"dependencies": [
"../llmr.gyp:llmr-x86"
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;
}