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 {
17 public:
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,
39 Duration single_token_update_interval);
40
41 /// Create an initially unbounded token bucket (largest size, instant refill)
42 static TokenBucket MakeUnbounded() noexcept;
43
44 TokenBucket(const TokenBucket&) = delete;
45 TokenBucket(TokenBucket&&) noexcept;
46 TokenBucket& operator=(const TokenBucket&) = delete;
47 TokenBucket& operator=(TokenBucket&&) noexcept;
48
49 bool IsUnbounded() const;
50
51 /// Get current token limit (might be inaccurate as the result is stale)
53
54 /// Get current refill amount (might be inaccurate as the result is stale)
56
57 /// Get current refill interval (might be inaccurate as the result is stale)
58 Duration GetRefillIntervalApprox() const;
59
60 /// Get rate (tokens per second)
61 double GetRatePs() const;
62
63 /// Get current token count (might be inaccurate as the result is stale)
65
66 /// Set max token count
67 void SetMaxSize(size_t max_size);
68
69 /// Add 1 token each token_update_interval.
70 /// Zero duration means "no limit".
71 [[deprecated]] void SetUpdateInterval(Duration single_token_update_interval);
72
73 /// Set refill policy for the bucket
75
76 /// Set refill policy to "instant refill".
77 ///
78 /// Obtain does not deplete the bucket in this mode.
79 /// Equivalent to `amount=1, interval=zero()` policy.
81
82 /// @returns true if token was successfully obtained
83 [[nodiscard]] bool Obtain();
84
85 /// @return true if the requested number of tokens was successfully obtained
86 [[nodiscard]] bool ObtainAll(size_t count);
87
88 /// Get rate for specified update interval (updates per second)
89 static double GetRatePs(Duration interval);
90
91 private:
92 void Update();
93
94 std::atomic<size_t> max_size_;
95 std::atomic<size_t> token_refill_amount_;
96 std::atomic<Duration> token_refill_interval_;
97 std::atomic<size_t> tokens_;
98 std::atomic<TimePoint> last_update_;
99};
100
101} // namespace utils
102
103USERVER_NAMESPACE_END