11#include <promeki/config.h>
12#if PROMEKI_ENABLE_CORE
18PROMEKI_NAMESPACE_BEGIN
69 bool fire() noexcept {
70 return !_fired.exchange(
true, MemoryOrder::AcqRel);
80 bool hasFired() const noexcept {
81 return _fired.value();
87 void reset() noexcept {
88 _fired.setValue(
false);
92 Atomic<bool> _fired{
false};
150 bool fire(int64_t intervalMs)
noexcept {
151 if (intervalMs <= 0)
return true;
152 const int64_t now = TimeStamp::now().milliseconds();
153 int64_t prev = _lastMs.value();
155 if (now - prev < intervalMs) {
156 _suppressed.fetchAndAdd(1, MemoryOrder::Relaxed);
159 if (_lastMs.compareAndSwap(prev, now))
return true;
170 uint64_t suppressedCount() const noexcept {
171 return _suppressed.value();
183 uint64_t consumeSuppressed() noexcept {
184 return _suppressed.exchange(0, MemoryOrder::AcqRel);
191 void reset() noexcept {
192 _lastMs.setValue(INT64_MIN / 2);
193 _suppressed.setValue(0);
197 Atomic<int64_t> _lastMs{INT64_MIN / 2};
198 Atomic<uint64_t> _suppressed{0};
232#define PROMEKI_ONCE \
233 for (static ::promeki::OnceGate _promeki_once_gate; _promeki_once_gate.fire();)
258#define PROMEKI_THROTTLED(intervalMs) \
259 for (static ::promeki::ThrottleGate _promeki_throttled_gate; \
260 _promeki_throttled_gate.fire(static_cast<int64_t>(intervalMs));)