From 2c631e4c8f430701e804f5f35151bb8798e55759 Mon Sep 17 00:00:00 2001 From: ItsMeSamey Date: Sat, 9 May 2026 19:15:44 +1000 Subject: [PATCH] introduced seperate class for waiting with timeout --- src/btop.cpp | 7 +++--- src/btop_shared.hpp | 6 ++++- src/btop_tools.cpp | 61 +++++++++++++++++++++++++++++++++++++++++---- src/btop_tools.hpp | 32 ++++++++++++++++++++++-- 4 files changed, 94 insertions(+), 12 deletions(-) diff --git a/src/btop.cpp b/src/btop.cpp index 3dbb5f9..94766c2 100644 --- a/src/btop.cpp +++ b/src/btop.cpp @@ -353,15 +353,14 @@ void init_config(bool low_color, std::optional& filter) { //* Manages secondary thread for collection and drawing of boxes namespace Runner { - atomic active (false); + atomic_waiting_lock active; atomic stopping (false); atomic waiting (false); atomic redraw (false); atomic coreNum_reset (false); static inline auto set_active(bool value) noexcept { - active.store(value, std::memory_order_release); - active.notify_all(); + active.store(value); } //* Setup semaphore for triggering thread to do work @@ -482,7 +481,7 @@ namespace Runner { } //? Atomic lock used for blocking non thread-safe actions in main thread - atomic_lock lck(active); + auto lck = active.lock(); //? Set effective user if SUID bit is set gain_priv powers{}; diff --git a/src/btop_shared.hpp b/src/btop_shared.hpp index c35a681..22818f2 100644 --- a/src/btop_shared.hpp +++ b/src/btop_shared.hpp @@ -51,6 +51,10 @@ using std::vector; using namespace std::literals; // for operator""s +namespace Tools { + class atomic_waiting_lock; +} + void term_resize(bool force=false); void banner_gen(); @@ -71,7 +75,7 @@ namespace Global { } namespace Runner { - extern atomic active; + extern Tools::atomic_waiting_lock active; extern atomic reading; extern atomic stopping; extern atomic redraw; diff --git a/src/btop_tools.cpp b/src/btop_tools.cpp index 752d210..76a2971 100644 --- a/src/btop_tools.cpp +++ b/src/btop_tools.cpp @@ -545,11 +545,6 @@ namespace Tools { atom.wait(old, std::memory_order_acquire); } - void atomic_wait_for(const atomic& atom, bool old, const uint64_t wait_ms) noexcept { - const uint64_t start_time = time_ms(); - while (atom.load(std::memory_order_acquire) == old and (time_ms() - start_time < wait_ms)) sleep_ms(1); - } - atomic_lock::atomic_lock(atomic& atom, bool wait) : atom(atom) { if (wait) { bool expected = false; @@ -564,6 +559,62 @@ namespace Tools { this->atom.notify_one(); } + void atomic_waiting_lock::store(bool new_value) noexcept { + { + std::lock_guard lock {mtx}; + value = new_value; + } + cv.notify_all(); + } + + void atomic_waiting_lock::wait(bool old) const noexcept { + std::unique_lock lock {mtx}; + cv.wait(lock, [this, old] { return value != old; }); + } + + void atomic_waiting_lock::wait_for(bool old, uint64_t wait_ms) const noexcept { + std::unique_lock lock {mtx}; + cv.wait_for(lock, std::chrono::milliseconds(wait_ms), [this, old] { return value != old; }); + } + + atomic_waiting_lock::guard atomic_waiting_lock::lock(bool wait) { + return guard(*this, wait); + } + + atomic_waiting_lock::operator bool() const noexcept { + std::lock_guard lock {mtx}; + return value; + } + + atomic_waiting_lock::guard::guard(atomic_waiting_lock& atom, bool wait) : atom(atom) { + if (wait) { + std::unique_lock lock {this->atom.mtx}; + this->atom.cv.wait(lock, [this] { return not this->atom.value; }); + this->atom.value = true; + } + else { + std::lock_guard lock {this->atom.mtx}; + this->atom.value = true; + } + this->atom.cv.notify_one(); + } + + atomic_waiting_lock::guard::~guard() noexcept { + { + std::lock_guard lock {this->atom.mtx}; + this->atom.value = false; + } + this->atom.cv.notify_one(); + } + + void atomic_wait(const atomic_waiting_lock& atom, bool old) noexcept { + atom.wait(old); + } + + void atomic_wait_for(const atomic_waiting_lock& atom, bool old, const uint64_t wait_ms) { + atom.wait_for(old, wait_ms); + } + string readfile(const std::filesystem::path& path, const string& fallback) { if (not fs::exists(path)) return fallback; string out; diff --git a/src/btop_tools.hpp b/src/btop_tools.hpp index 64b957b..e0285bf 100644 --- a/src/btop_tools.hpp +++ b/src/btop_tools.hpp @@ -26,9 +26,11 @@ tab-size = 4 #include #include #include +#include #include #include #include +#include #include #include #include @@ -366,8 +368,6 @@ namespace Tools { void atomic_wait(const atomic& atom, bool old = true) noexcept; - void atomic_wait_for(const atomic& atom, bool old = true, const uint64_t wait_ms = 0) noexcept; - //* Sets atomic to true on construct, sets to false on destruct class atomic_lock { atomic& atom; @@ -380,6 +380,34 @@ namespace Tools { atomic_lock& operator=(atomic_lock&& other) = delete; }; + class atomic_waiting_lock { + bool value{}; + mutable std::mutex mtx; + mutable std::condition_variable cv; + + public: + class guard { + atomic_waiting_lock& atom; + public: + explicit guard(atomic_waiting_lock& atom, bool wait = false); + ~guard() noexcept; + guard(const guard& other) = delete; + guard& operator=(const guard& other) = delete; + guard(guard&& other) = delete; + guard& operator=(guard&& other) = delete; + }; + + void store(bool value) noexcept; + void wait(bool old = true) const noexcept; + void wait_for(bool old, uint64_t wait_ms) const noexcept; + [[nodiscard]] guard lock(bool wait = false); + explicit operator bool() const noexcept; + }; + + void atomic_wait(const atomic_waiting_lock& atom, bool old = true) noexcept; + + void atomic_wait_for(const atomic_waiting_lock& atom, bool old = true, const uint64_t wait_ms = 0); + //* Read a complete file and return as a string string readfile(const std::filesystem::path& path, const string& fallback = "");