commits
tags
#include "torlinkc/ui/coalescing_notifier.hpp"
namespace torlinkc::ui {
CoalescingNotifier::CoalescingNotifier(std::chrono::milliseconds window, std::function<void()> onFlush)
: window_(window), onFlush_(std::move(onFlush)) {
thread_ = std::thread([this] { run(); });
}
CoalescingNotifier::~CoalescingNotifier() {
{
std::lock_guard<std::mutex> lock(mutex_);
stop_ = true;
}
cv_.notify_all();
if (thread_.joinable()) thread_.join();
}
void CoalescingNotifier::markDirty() {
std::lock_guard<std::mutex> lock(mutex_);
dirty_ = true;
cv_.notify_all();
}
void CoalescingNotifier::flushNow() {
std::lock_guard<std::mutex> lock(mutex_);
dirty_ = true;
flushRequested_ = true;
cv_.notify_all();
}
void CoalescingNotifier::run() {
std::unique_lock<std::mutex> lock(mutex_);
while (!stop_) {
cv_.wait(lock, [this] { return dirty_ || stop_; });
if (stop_) break;
// Wait out the coalescing window, unless flushNow() or stop wakes us
// early -- this is the "further calls before the deadline are absorbed"
// half of the contract: any markDirty() during this wait just leaves
// dirty_ (already) true without re-arming a fresh window.
cv_.wait_for(lock, window_, [this] { return flushRequested_ || stop_; });
if (stop_) break;
dirty_ = false;
flushRequested_ = false;
lock.unlock();
onFlush_();
lock.lock();
}
}
} // namespace torlinkc::ui