From 70bdeb79c3be7de0a09e7398b6300135b7b0b6c2 Mon Sep 17 00:00:00 2001 From: nerix Date: Thu, 3 Jul 2025 23:22:15 +0200 Subject: [PATCH] fix(OnceFlag): add `isSet` and check before waiting (#6316) --- CHANGELOG.md | 2 +- src/util/OnceFlag.cpp | 14 ++++++++++++++ src/util/OnceFlag.hpp | 3 +++ tests/src/OnceFlag.cpp | 21 +++++++++++++++++++++ 4 files changed, 39 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 01c010b7..04e5fdaf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -68,7 +68,7 @@ - Dev: Refactored `Button` and friends. (#6102, #6255, #6266, #6302, #6268) - Dev: Made Settings & Account button on Linux/macOS SVGs. (#6267) - Dev: Emoji style / set is now stored lowercase (and matched case-insensitively). Changing emoji style from this point on and then running an old version might mean you will use the Twitter emoji style by default. (#6300) -- Dev: `OnceFlag`'s internal flag is now atomic. (#6237) +- Dev: Refactored `OnceFlag`. (#6237, #6316) - Dev: Bumped clang-format requirement to 19. (#6236) ## 2.5.3 diff --git a/src/util/OnceFlag.cpp b/src/util/OnceFlag.cpp index 8ec2f951..062ff01a 100644 --- a/src/util/OnceFlag.cpp +++ b/src/util/OnceFlag.cpp @@ -16,6 +16,10 @@ void OnceFlag::set() bool OnceFlag::waitFor(std::chrono::milliseconds ms) { std::unique_lock lock(this->mutex); + if (this->flag.load(std::memory_order::relaxed)) + { + return true; + } return this->condvar.wait_for(lock, ms, [this] { return this->flag.load(std::memory_order::relaxed); }); @@ -24,9 +28,19 @@ bool OnceFlag::waitFor(std::chrono::milliseconds ms) void OnceFlag::wait() { std::unique_lock lock(this->mutex); + if (this->flag.load(std::memory_order::relaxed)) + { + return; + } this->condvar.wait(lock, [this] { return this->flag.load(std::memory_order::relaxed); }); } +bool OnceFlag::isSet() +{ + std::unique_lock lock(this->mutex); + return this->flag.load(std::memory_order::relaxed); +} + } // namespace chatterino diff --git a/src/util/OnceFlag.hpp b/src/util/OnceFlag.hpp index 7d5aeb9f..c66d112a 100644 --- a/src/util/OnceFlag.hpp +++ b/src/util/OnceFlag.hpp @@ -31,6 +31,9 @@ public: /// The calling thread will be suspended during the wait. void wait(); + /// Is the flag currently set? + bool isSet(); + private: std::mutex mutex; std::condition_variable condvar; diff --git a/tests/src/OnceFlag.cpp b/tests/src/OnceFlag.cpp index 3f93b48e..f2260655 100644 --- a/tests/src/OnceFlag.cpp +++ b/tests/src/OnceFlag.cpp @@ -79,10 +79,31 @@ TEST(OnceFlag, waitForTimeout) }); startedFlag.wait(); + ASSERT_TRUE(startedFlag.isSet()); startedAckFlag.set(); + ASSERT_TRUE(startedAckFlag.isSet()); ASSERT_FALSE(stoppedFlag.waitFor(std::chrono::milliseconds{25})); stoppedFlag.wait(); + ASSERT_TRUE(stoppedFlag.isSet()); t.join(); } + +TEST(OnceFlag, alreadySet) +{ + OnceFlag flag; + flag.set(); + ASSERT_TRUE(flag.isSet()); + + auto start = std::chrono::system_clock::now(); + flag.wait(); + auto stop = std::chrono::system_clock::now(); + ASSERT_LT(stop - start, std::chrono::milliseconds{10}); + + start = std::chrono::system_clock::now(); + ASSERT_TRUE(flag.waitFor(std::chrono::milliseconds{0})); + stop = std::chrono::system_clock::now(); + + ASSERT_LT(stop - start, std::chrono::milliseconds{10}); +}