HTTPDownloader: Use release-acquire ordering for request state

This commit is contained in:
Stenzek
2025-11-29 15:23:21 +10:00
parent a171c25fb2
commit d6f7084309
2 changed files with 18 additions and 16 deletions

View File

@@ -98,20 +98,21 @@ void HTTPDownloader::LockedPollRequests(std::unique_lock<std::mutex>& 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<std::mutex>& 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<std::mutex>& 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;

View File

@@ -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;