From d6f708430910a02ff4f56c4d2ebdbac2dccba2eb Mon Sep 17 00:00:00 2001 From: Stenzek Date: Sat, 29 Nov 2025 15:23:21 +1000 Subject: [PATCH] HTTPDownloader: Use release-acquire ordering for request state --- src/util/http_downloader.cpp | 18 ++++++++++-------- src/util/http_downloader_winhttp.cpp | 16 ++++++++-------- 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/util/http_downloader.cpp b/src/util/http_downloader.cpp index c29cc97d6..b10325d8d 100644 --- a/src/util/http_downloader.cpp +++ b/src/util/http_downloader.cpp @@ -98,20 +98,21 @@ void HTTPDownloader::LockedPollRequests(std::unique_lock& lock) for (size_t index = 0; index < m_pending_http_requests.size();) { Request* req = m_pending_http_requests[index]; - if (req->state == Request::State::Pending) + const Request::State req_state = req->state.load(std::memory_order_acquire); + if (req_state == Request::State::Pending) { unstarted_requests++; index++; continue; } - if ((req->state == Request::State::Started || req->state == Request::State::Receiving) && + if ((req_state == Request::State::Started || req_state == Request::State::Receiving) && current_time >= req->start_time && Timer::ConvertValueToSeconds(current_time - req->start_time) >= m_timeout) { // request timed out ERROR_LOG("Request for '{}' timed out", req->url); - req->state.store(Request::State::Cancelled); + req->state.store(Request::State::Cancelled, std::memory_order_release); m_pending_http_requests.erase(m_pending_http_requests.begin() + index); lock.unlock(); @@ -123,13 +124,13 @@ void HTTPDownloader::LockedPollRequests(std::unique_lock& lock) lock.lock(); continue; } - else if ((req->state == Request::State::Started || req->state == Request::State::Receiving) && req->progress && + else if ((req_state == Request::State::Started || req_state == Request::State::Receiving) && req->progress && req->progress->IsCancelled()) { // request timed out ERROR_LOG("Request for '{}' cancelled", req->url); - req->state.store(Request::State::Cancelled); + req->state.store(Request::State::Cancelled, std::memory_order_release); m_pending_http_requests.erase(m_pending_http_requests.begin() + index); lock.unlock(); @@ -142,7 +143,7 @@ void HTTPDownloader::LockedPollRequests(std::unique_lock& lock) continue; } - if (req->state != Request::State::Complete) + if (req_state != Request::State::Complete) { if (req->progress) { @@ -245,9 +246,10 @@ void HTTPDownloader::LockedAddRequest(Request* request) u32 HTTPDownloader::LockedGetActiveRequestCount() { u32 count = 0; - for (Request* req : m_pending_http_requests) + for (const Request* const req : m_pending_http_requests) { - if (req->state == Request::State::Started || req->state == Request::State::Receiving) + const Request::State req_state = req->state.load(std::memory_order_acquire); + if (req_state == Request::State::Started || req_state == Request::State::Receiving) count++; } return count; diff --git a/src/util/http_downloader_winhttp.cpp b/src/util/http_downloader_winhttp.cpp index 8bb7938cd..09993bf8d 100644 --- a/src/util/http_downloader_winhttp.cpp +++ b/src/util/http_downloader_winhttp.cpp @@ -127,7 +127,7 @@ void CALLBACK HTTPDownloaderWinHttp::HTTPStatusCallback(HINTERNET hRequest, DWOR ERROR_LOG("WinHttp async function {} returned error {}", res->dwResult, res->dwError); req->status_code = HTTP_STATUS_ERROR; req->error.SetStringFmt("WinHttp async function {} returned error {}", res->dwResult, res->dwError); - req->state.store(Request::State::Complete); + req->state.store(Request::State::Complete, std::memory_order_release); return; } case WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE: @@ -139,7 +139,7 @@ void CALLBACK HTTPDownloaderWinHttp::HTTPStatusCallback(HINTERNET hRequest, DWOR ERROR_LOG("WinHttpReceiveResponse() failed: {}", err); req->status_code = HTTP_STATUS_ERROR; req->error.SetWin32("WinHttpReceiveResponse() failed: ", err); - req->state.store(Request::State::Complete); + req->state.store(Request::State::Complete, std::memory_order_release); } return; @@ -156,7 +156,7 @@ void CALLBACK HTTPDownloaderWinHttp::HTTPStatusCallback(HINTERNET hRequest, DWOR ERROR_LOG("WinHttpQueryHeaders() for status code failed: {}", err); req->status_code = HTTP_STATUS_ERROR; req->error.SetWin32("WinHttpQueryHeaders() failed: ", err); - req->state.store(Request::State::Complete); + req->state.store(Request::State::Complete, std::memory_order_release); return; } @@ -188,7 +188,7 @@ void CALLBACK HTTPDownloaderWinHttp::HTTPStatusCallback(HINTERNET hRequest, DWOR DEV_LOG("Status code {}, content-length is {}", req->status_code, req->content_length); req->data.reserve(req->content_length); - req->state = Request::State::Receiving; + req->state.store(Request::State::Receiving, std::memory_order_release); // start reading if (!WinHttpQueryDataAvailable(hRequest, nullptr) && GetLastError() != ERROR_IO_PENDING) @@ -197,7 +197,7 @@ void CALLBACK HTTPDownloaderWinHttp::HTTPStatusCallback(HINTERNET hRequest, DWOR ERROR_LOG("WinHttpQueryDataAvailable() failed: {}", err); req->status_code = HTTP_STATUS_ERROR; req->error.SetWin32("WinHttpQueryDataAvailable() failed: ", err); - req->state.store(Request::State::Complete); + req->state.store(Request::State::Complete, std::memory_order_release); } return; @@ -210,7 +210,7 @@ void CALLBACK HTTPDownloaderWinHttp::HTTPStatusCallback(HINTERNET hRequest, DWOR { // end of request DEV_LOG("End of request '{}', {} bytes received", req->url, req->data.size()); - req->state.store(Request::State::Complete); + req->state.store(Request::State::Complete, std::memory_order_release); return; } @@ -225,7 +225,7 @@ void CALLBACK HTTPDownloaderWinHttp::HTTPStatusCallback(HINTERNET hRequest, DWOR ERROR_LOG("WinHttpReadData() failed: {}", err); req->status_code = HTTP_STATUS_ERROR; req->error.SetWin32("WinHttpReadData() failed: ", err); - req->state.store(Request::State::Complete); + req->state.store(Request::State::Complete, std::memory_order_release); } return; @@ -245,7 +245,7 @@ void CALLBACK HTTPDownloaderWinHttp::HTTPStatusCallback(HINTERNET hRequest, DWOR ERROR_LOG("WinHttpQueryDataAvailable() failed: {}", err); req->status_code = HTTP_STATUS_ERROR; req->error.SetWin32("WinHttpQueryDataAvailable() failed: ", err); - req->state.store(Request::State::Complete); + req->state.store(Request::State::Complete, std::memory_order_release); } return;