Mercurial > minori
diff src/core/http.cc @ 390:2d3e10319112
http: optimize HTTP request thread
we don't need a mutex at all, in fact all we need is an atomic
boolean to signify whether the thread is cancelled.
curl options are now for the most part handled by a separate
function to keep them in sync between non-threaded and threaded
implementations
| author | Paper <paper@tflc.us> |
|---|---|
| date | Fri, 07 Nov 2025 07:08:57 -0500 |
| parents | 1e5d922fe82b |
| children | 963047512d34 |
line wrap: on
line diff
--- a/src/core/http.cc Thu Nov 06 12:21:35 2025 -0500 +++ b/src/core/http.cc Fri Nov 07 07:08:57 2025 -0500 @@ -65,6 +65,32 @@ return base; } +static void SetCurlOpts(CURL *curl, const std::string &url, const std::vector<std::string> &headers, const std::string &data, Type type) +{ + struct curl_slist *list; + + curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); + + list = NULL; + for (const std::string &h : headers) + list = curl_slist_append(list, h.c_str()); + curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); + + switch (type) { + case Type::Patch: + curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PATCH"); + [[fallthrough]]; + case Type::Post: + curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str()); + break; + case Type::Get: + break; + } + + curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NATIVE_CA); + curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L); // threading +} + static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userdata) { reinterpret_cast<QByteArray *>(userdata)->append(reinterpret_cast<char *>(contents), size * nmemb); @@ -73,25 +99,17 @@ QByteArray Request(const std::string &url, const std::vector<std::string> &headers, const std::string &data, Type type) { - struct curl_slist *list = NULL; QByteArray userdata; CURL *curl = curl_easy_init(); if (curl) { - for (const std::string &h : headers) - list = curl_slist_append(list, h.c_str()); + SetCurlOpts(curl, url, headers, data, type); - curl_easy_setopt(curl, CURLOPT_URL, url.c_str()); - if (type == Type::Post || type == Type::Patch) - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data.c_str()); - if (type == Type::Patch) - curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PATCH"); - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); + /* Use our specific userdata & write callback + * TODO can this just be a lambda instead */ curl_easy_setopt(curl, CURLOPT_WRITEDATA, &userdata); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &WriteCallback); - /* Use system certs... useful on Windows. */ - curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NATIVE_CA); - curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L); // threading + CURLcode res = curl_easy_perform(curl); session.IncrementRequests(); curl_easy_cleanup(curl); @@ -106,9 +124,6 @@ { RequestThread *thread = reinterpret_cast<RequestThread *>(userdata); - const std::lock_guard<std::mutex> lock(thread->callback_data_mutex_); - - /* stop writing, then! */ if (thread->cancelled_) return CURL_WRITEFUNC_ERROR; @@ -137,6 +152,10 @@ /* block until the function can safely exit */ Stop(); wait(); + + /* Kill off any curl thing we made */ + if (curl_) + curl_easy_cleanup(reinterpret_cast<CURL *>(curl_)); } void RequestThread::SetUrl(const std::string &url) @@ -161,45 +180,34 @@ void RequestThread::run() { - struct curl_slist *list = NULL; - - CURL *curl = curl_easy_init(); - if (curl) { - curl_easy_setopt(curl, CURLOPT_URL, url_.c_str()); + /* If we don't have a curl object, create one */ + if (!curl_) { + curl_ = reinterpret_cast<void *>(curl_easy_init()); + } - if (type_ == Type::Post || type_ == Type::Patch) - curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data_.c_str()); + CURL *curl = reinterpret_cast<CURL *>(curl_); - for (const std::string &h : headers_) - list = curl_slist_append(list, h.c_str()); - curl_easy_setopt(curl, CURLOPT_HTTPHEADER, list); + if (curl) { + SetCurlOpts(curl, url_, headers_, data_, type_); curl_easy_setopt(curl, CURLOPT_WRITEDATA, this); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &RequestThread::WriteCallback); - /* Use system certs... useful on Windows. */ - curl_easy_setopt(curl, CURLOPT_SSL_OPTIONS, CURLSSLOPT_NATIVE_CA); - - /* does something with threading, don't remember what though */ - curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1L); - CURLcode res = curl_easy_perform(curl); session.IncrementRequests(); curl_easy_cleanup(curl); - callback_data_mutex_.lock(); if (res != CURLE_OK && !(res == CURLE_WRITE_ERROR && cancelled_)) session.SetStatusBar(std::string("curl_easy_perform(curl) failed!: ") + curl_easy_strerror(res)); - callback_data_mutex_.unlock(); } emit ReceivedData(array_); + /* Clear it out for any subsequent runs */ array_.clear(); } void RequestThread::Stop() { - const std::lock_guard<std::mutex> lock(callback_data_mutex_); cancelled_ = true; }
