[WGPUFuture] Use map over unordered_map for JS event ordering.
Bug: dawn:2066
Change-Id: Ie8e720c5e48f3e471a8eb5fe1019bcd0441583ad
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/153000
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Loko Kung <lokokung@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/dawn/wire/client/EventManager.cpp b/src/dawn/wire/client/EventManager.cpp
index f567078..1e0f1e0 100644
--- a/src/dawn/wire/client/EventManager.cpp
+++ b/src/dawn/wire/client/EventManager.cpp
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-#include <unordered_map>
+#include <map>
#include <utility>
#include <vector>
@@ -47,13 +47,14 @@
void EventManager::ShutDown() {
// Call any outstanding callbacks before destruction.
while (true) {
- std::unordered_map<FutureID, TrackedEvent> movedEvents;
+ std::map<FutureID, TrackedEvent> movedEvents;
mTrackedEvents.Use([&](auto trackedEvents) { movedEvents = std::move(*trackedEvents); });
if (movedEvents.empty()) {
break;
}
+ // Ordering guaranteed because we are using a sorted map.
for (auto& [futureID, trackedEvent] : movedEvents) {
// Event should be already marked Ready since events are actually driven by
// RequestTrackers (at the time of this writing), which all shut down before this.
@@ -74,6 +75,7 @@
}
void EventManager::ProcessPollEvents() {
+ // Since events are already stored in an ordered map, this list must already be ordered.
std::vector<TrackedEvent> eventsToCompleteNow;
// TODO(crbug.com/dawn/2060): EventManager shouldn't bother to track ProcessEvents-type events
@@ -120,7 +122,9 @@
return WGPUWaitStatus_Success;
}
- std::vector<TrackedEvent> eventsToCompleteNow;
+ // Since the user can specify the FutureIDs in any order, we need to use another ordered map
+ // here to ensure that the result is ordered for JS event ordering.
+ std::map<FutureID, TrackedEvent> eventsToCompleteNow;
bool anyCompleted = false;
const FutureID firstInvalidFutureID = mNextFutureID;
mTrackedEvents.Use([&](auto trackedEvents) {
@@ -141,7 +145,7 @@
if (event.mReady) {
anyCompleted = true;
if (event.mCallback) {
- eventsToCompleteNow.emplace_back(std::move(event));
+ eventsToCompleteNow.emplace(it->first, std::move(event));
}
trackedEvents->erase(it);
}
@@ -149,7 +153,7 @@
});
// TODO(crbug.com/dawn/2066): Guarantee the event ordering from the JS spec.
- for (TrackedEvent& event : eventsToCompleteNow) {
+ for (auto& [_, event] : eventsToCompleteNow) {
DAWN_ASSERT(event.mReady && event.mCallback);
// .completed has already been set to true (before the callback, per API contract).
event.mCallback(EventCompletionType::Ready);
diff --git a/src/dawn/wire/client/EventManager.h b/src/dawn/wire/client/EventManager.h
index 2260b73..2c599e2 100644
--- a/src/dawn/wire/client/EventManager.h
+++ b/src/dawn/wire/client/EventManager.h
@@ -17,7 +17,7 @@
#include <cstddef>
#include <functional>
-#include <unordered_map>
+#include <map>
#include <utility>
#include "dawn/common/FutureUtils.h"
@@ -70,8 +70,10 @@
Client* mClient;
- // Tracks all kinds of events (for both WaitAny and ProcessEvents).
- MutexProtected<std::unordered_map<FutureID, TrackedEvent>> mTrackedEvents;
+ // Tracks all kinds of events (for both WaitAny and ProcessEvents). We use an ordered map so
+ // that in most cases, event ordering is already implicit when we iterate the map. (Not true for
+ // WaitAny though because the user could specify the FutureIDs out of order.)
+ MutexProtected<std::map<FutureID, TrackedEvent>> mTrackedEvents;
std::atomic<FutureID> mNextFutureID = 1;
};