libpromeki 1.0.0-alpha
PROfessional MEdia toolKIt
 
Loading...
Searching...
No Matches
gate.h
Go to the documentation of this file.
1
8#pragma once
9
10
11#include <promeki/config.h>
12#if PROMEKI_ENABLE_CORE
13#include <cstdint>
14#include <promeki/atomic.h>
15#include <promeki/namespace.h>
16#include <promeki/timestamp.h>
17
18PROMEKI_NAMESPACE_BEGIN
19
58class OnceGate {
59 public:
69 bool fire() noexcept {
70 return !_fired.exchange(true, MemoryOrder::AcqRel);
71 }
72
80 bool hasFired() const noexcept {
81 return _fired.value();
82 }
83
87 void reset() noexcept {
88 _fired.setValue(false);
89 }
90
91 private:
92 Atomic<bool> _fired{false};
93};
94
131class ThrottleGate {
132 public:
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();
154 for (;;) {
155 if (now - prev < intervalMs) {
156 _suppressed.fetchAndAdd(1, MemoryOrder::Relaxed);
157 return false;
158 }
159 if (_lastMs.compareAndSwap(prev, now)) return true;
160 // prev was updated by compareAndSwap; retry.
161 }
162 }
163
170 uint64_t suppressedCount() const noexcept {
171 return _suppressed.value();
172 }
173
183 uint64_t consumeSuppressed() noexcept {
184 return _suppressed.exchange(0, MemoryOrder::AcqRel);
185 }
186
191 void reset() noexcept {
192 _lastMs.setValue(INT64_MIN / 2);
193 _suppressed.setValue(0);
194 }
195
196 private:
197 Atomic<int64_t> _lastMs{INT64_MIN / 2};
198 Atomic<uint64_t> _suppressed{0};
199};
200
201PROMEKI_NAMESPACE_END
202
232#define PROMEKI_ONCE \
233 for (static ::promeki::OnceGate _promeki_once_gate; _promeki_once_gate.fire();)
234
258#define PROMEKI_THROTTLED(intervalMs) \
259 for (static ::promeki::ThrottleGate _promeki_throttled_gate; \
260 _promeki_throttled_gate.fire(static_cast<int64_t>(intervalMs));)
261
262#endif // PROMEKI_ENABLE_CORE