Allow WaitListEvent to require multiple signals.
Change the atomic bool in WaitListEvent to a counter and require
multiple Signal calls before marking the event as complete.
Bug: 406522796
Change-Id: I2bb5c8d24d0af550a37c54c5dd70a5a57db290f2
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/259254
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Loko Kung <lokokung@google.com>
Commit-Queue: Geoff Lang <geofflang@chromium.org>
diff --git a/src/dawn/native/WaitListEvent.cpp b/src/dawn/native/WaitListEvent.cpp
index 70f4420..3cf921b 100644
--- a/src/dawn/native/WaitListEvent.cpp
+++ b/src/dawn/native/WaitListEvent.cpp
@@ -33,16 +33,21 @@
namespace dawn::native {
-WaitListEvent::WaitListEvent() = default;
+WaitListEvent::WaitListEvent(uint64_t requiredSignalCount)
+ : mRemainingSignalCount(requiredSignalCount) {
+ DAWN_ASSERT(mRemainingSignalCount > 0);
+}
WaitListEvent::~WaitListEvent() = default;
bool WaitListEvent::IsSignaled() const {
- return mSignaled.load(std::memory_order_acquire);
+ return mRemainingSignalCount.load(std::memory_order_acquire) == 0;
}
void WaitListEvent::Signal() {
- std::lock_guard<std::mutex> lock(mMutex);
- if (!mSignaled.exchange(true, std::memory_order_release)) {
+ uint64_t prevSignalCount = mRemainingSignalCount.fetch_sub(1, std::memory_order_release);
+ DAWN_ASSERT(prevSignalCount != 0);
+ if (prevSignalCount == 1) {
+ std::lock_guard<std::mutex> lock(mMutex);
for (SyncWaiter* w : std::move(mSyncWaiters)) {
{
std::lock_guard<std::mutex> waiterLock(w->mutex);
diff --git a/src/dawn/native/WaitListEvent.h b/src/dawn/native/WaitListEvent.h
index fbb85b0..109df76 100644
--- a/src/dawn/native/WaitListEvent.h
+++ b/src/dawn/native/WaitListEvent.h
@@ -45,7 +45,7 @@
class WaitListEvent : public RefCounted {
public:
- WaitListEvent();
+ explicit WaitListEvent(uint64_t requiredSignalCount = 1);
bool IsSignaled() const;
void Signal();
@@ -65,7 +65,7 @@
};
mutable std::mutex mMutex;
- std::atomic_bool mSignaled{false};
+ std::atomic<uint64_t> mRemainingSignalCount;
std::vector<raw_ptr<SyncWaiter>> mSyncWaiters;
std::vector<SystemEventPipeSender> mAsyncWaiters;
};
diff --git a/src/dawn/tests/white_box/WaitListEventTests.cpp b/src/dawn/tests/white_box/WaitListEventTests.cpp
index b97c7c9..bc66255 100644
--- a/src/dawn/tests/white_box/WaitListEventTests.cpp
+++ b/src/dawn/tests/white_box/WaitListEventTests.cpp
@@ -347,5 +347,16 @@
signaler.join();
}
+// Test events that require multiple signal calls
+TEST(WaitListEventTests, MultipleSignals) {
+ constexpr uint64_t kSignalCount = 10;
+ Ref<WaitListEvent> event1 = AcquireRef(new WaitListEvent(kSignalCount));
+ for (uint64_t i = 0; i < kSignalCount; i++) {
+ EXPECT_FALSE(event1->IsSignaled());
+ event1->Signal();
+ }
+ EXPECT_TRUE(event1->IsSignaled());
+}
+
} // namespace
} // namespace dawn::native