userver: userver/utils/token_bucket.hpp Source File
Loading...
Searching...
No Matches
token_bucket.hpp
Go to the documentation of this file.
1#pragma once
2
3/// @file userver/utils/token_bucket.hpp
4/// @brief @copybrief utils::TokenBucket
5
6#include <atomic>
7#include <chrono>
8
9USERVER_NAMESPACE_BEGIN
10
11namespace utils {
12
13/// @ingroup userver_universal userver_concurrency
14///
15/// Thread safe ratelimiter
16class TokenBucket final {
17public:
18 using TimePoint = std::chrono::steady_clock::time_point;
19 using Duration = std::chrono::steady_clock::duration;
20
21 /// Token bucket refill policy
22 struct RefillPolicy {
23 /// Refill amount (zero disables refills)
25 /// Refill interval (zero makes bucket to instantly refill)
26 Duration interval{Duration::max()};
27 };
28
29 /// Create an initially always empty token bucket
30 TokenBucket() noexcept;
31
32 /// Create a token bucket with max_size tokens and a specified refill policy
33 TokenBucket(size_t max_size, RefillPolicy policy);
34
35 /// Start with max_size tokens and add 1 token each
36 /// single_token_update_interval up to max_size.
37 /// Zero duration means "no limit".
38 [[deprecated]] TokenBucket(size_t max_size, Duration single_token_update_interval);
39
40 /// Create an initially unbounded token bucket (largest size, instant refill)
41 static TokenBucket MakeUnbounded() noexcept;
42
43 TokenBucket(const TokenBucket&) = delete;
44 TokenBucket(TokenBucket&&) noexcept;
45 TokenBucket& operator=(const TokenBucket&) = delete;
46 TokenBucket& operator=(TokenBucket&&) noexcept;
47
48 bool IsUnbounded() const;
49
50 /// Get current token limit (might be inaccurate as the result is stale)
52
53 /// Get current refill amount (might be inaccurate as the result is stale)
55
56 /// Get current refill interval (might be inaccurate as the result is stale)
57 Duration GetRefillIntervalApprox() const;
58
59 /// Get rate (tokens per second)
60 double GetRatePs() const;
61
62 /// Get current token count (might be inaccurate as the result is stale)
64
65 /// Set max token count
66 void SetMaxSize(size_t max_size);
67
68 /// Add 1 token each token_update_interval.
69 /// Zero duration means "no limit".
70 [[deprecated]] void SetUpdateInterval(Duration single_token_update_interval);
71
72 /// Set refill policy for the bucket
74
75 /// Set refill policy to "instant refill".
76 ///
77 /// Obtain does not deplete the bucket in this mode.
78 /// Equivalent to `amount=1, interval=zero()` policy.
80
81 /// @returns true if token was successfully obtained
82 [[nodiscard]] bool Obtain();
83
84 /// @return true if the requested number of tokens was successfully obtained
85 [[nodiscard]] bool ObtainAll(size_t count);
86
87 /// Get rate for specified update interval (updates per second)
88 static double GetRatePs(Duration interval);
89
90private:
91 void Update();
92
93 std::atomic<size_t> max_size_;
94 std::atomic<size_t> token_refill_amount_;
95 std::atomic<Duration> token_refill_interval_;
96 std::atomic<size_t> tokens_;
97 std::atomic<TimePoint> last_update_;
98};
99
100} // namespace utils
101
102USERVER_NAMESPACE_END