summaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
authorThiago Marcos P. Santos <thiago@mapbox.com>2016-02-16 15:51:40 +0200
committerThiago Marcos P. Santos <thiago@mapbox.com>2016-02-16 23:06:04 +0200
commitf5b521ffb51e396be322350a204b835a0bf0af08 (patch)
treeed975762556873684d93146ebba6002c532a1076 /platform
parentd66d145c6e90dabe442c384fe2a10aef4f0a4fbb (diff)
downloadqtlocation-mapboxgl-f5b521ffb51e396be322350a204b835a0bf0af08.tar.gz
[core] Remove requests from the pending queue on cancel
If we don't do this, we can activate a request twice. The issue here is that we use memory address as the 'key'. So if we destroy a request, another request might take the same memory address, or the same 'key'. The entry at 'pendingRequests' survives the 'cancel()' and is ultimatelly removed at 'activatePendingRequest()'. This is fine unless a request is created using the same 'key' before we call 'activatePendingRequest()'. The check if the request was canceled at 'activatePendingRequest()' will be no longer valid, activating the request. At the same time the request will be activated again by the task scheduled at the constructor of the 'OnlineFileRequestImpl' class.
Diffstat (limited to 'platform')
-rw-r--r--platform/default/online_file_source.cpp34
1 files changed, 21 insertions, 13 deletions
diff --git a/platform/default/online_file_source.cpp b/platform/default/online_file_source.cpp
index a095b86fba..43c707775d 100644
--- a/platform/default/online_file_source.cpp
+++ b/platform/default/online_file_source.cpp
@@ -15,6 +15,7 @@
#include <algorithm>
#include <cassert>
+#include <list>
#include <set>
#include <unordered_map>
@@ -62,6 +63,12 @@ public:
allRequests.erase(key);
if (activeRequests.erase(key)) {
activatePendingRequest();
+ } else {
+ auto it = pendingRequestsMap.find(key);
+ if (it != pendingRequestsMap.end()) {
+ pendingRequestsList.erase(it->second);
+ pendingRequestsMap.erase(it);
+ }
}
}
@@ -78,7 +85,8 @@ public:
}
void queueRequest(OnlineFileRequestImpl* impl) {
- pendingRequests.push(impl->key);
+ auto it = pendingRequestsList.insert(pendingRequestsList.end(), impl->key);
+ pendingRequestsMap.emplace(impl->key, std::move(it));
}
void activateRequest(OnlineFileRequestImpl* impl) {
@@ -92,19 +100,18 @@ public:
}
void activatePendingRequest() {
- while (!pendingRequests.empty()) {
- FileRequest* key = pendingRequests.front();
- pendingRequests.pop();
-
- auto it = allRequests.find(key);
- if (it == allRequests.end()) {
- // It must have been cancelled.
- continue;
- }
-
- activateRequest(it->second.get());
+ if (pendingRequestsList.empty()) {
return;
}
+
+ FileRequest* key = pendingRequestsList.front();
+ pendingRequestsList.pop_front();
+
+ pendingRequestsMap.erase(key);
+
+ auto it = allRequests.find(key);
+ assert(it != allRequests.end());
+ activateRequest(it->second.get());
}
private:
@@ -126,7 +133,8 @@ private:
* `pendingRequests`. Requests in the active state are in `activeRequests`.
*/
std::unordered_map<FileRequest*, std::unique_ptr<OnlineFileRequestImpl>> allRequests;
- std::queue<FileRequest*> pendingRequests;
+ std::list<FileRequest*> pendingRequestsList;
+ std::unordered_map<FileRequest*, std::list<FileRequest*>::iterator> pendingRequestsMap;
std::set<FileRequest*> activeRequests;
const std::unique_ptr<HTTPContextBase> httpContext { HTTPContextBase::createContext() };