tokenquota.h 2.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. #pragma once
  2. #include <library/cpp/deprecated/atomic/atomic.h>
  3. namespace NBus {
  4. /* Consumer and feeder quota model impl.
  5. Consumer thread only calls:
  6. Acquire(), fetches tokens for usage from bucket;
  7. Consume(), eats given amount of tokens, must not
  8. be greater than Value() items;
  9. Other threads (feeders) calls:
  10. Return(), put used tokens back to bucket;
  11. */
  12. class TTokenQuota {
  13. public:
  14. TTokenQuota(bool enabled, size_t tokens, size_t wake)
  15. : Enabled(tokens > 0 ? enabled : false)
  16. , Acquired(0)
  17. , WakeLev(wake < 1 ? Max<size_t>(1, tokens / 2) : 0)
  18. , Tokens_(tokens)
  19. {
  20. Y_UNUSED(padd_);
  21. }
  22. bool Acquire(TAtomicBase level = 1, bool force = false) {
  23. level = Max(TAtomicBase(level), TAtomicBase(1));
  24. if (Enabled && (Acquired < level || force)) {
  25. Acquired += AtomicSwap(&Tokens_, 0);
  26. }
  27. return !Enabled || Acquired >= level;
  28. }
  29. void Consume(size_t items) {
  30. if (Enabled) {
  31. Y_ASSERT(Acquired >= TAtomicBase(items));
  32. Acquired -= items;
  33. }
  34. }
  35. bool Return(size_t items_) noexcept {
  36. if (!Enabled || items_ == 0)
  37. return false;
  38. const TAtomic items = items_;
  39. const TAtomic value = AtomicAdd(Tokens_, items);
  40. return (value - items < WakeLev && value >= WakeLev);
  41. }
  42. bool IsEnabled() const noexcept {
  43. return Enabled;
  44. }
  45. bool IsAboveWake() const noexcept {
  46. return !Enabled || (WakeLev <= AtomicGet(Tokens_));
  47. }
  48. size_t Tokens() const noexcept {
  49. return Acquired + AtomicGet(Tokens_);
  50. }
  51. size_t Check(const TAtomicBase level) const noexcept {
  52. return !Enabled || level <= Acquired;
  53. }
  54. private:
  55. bool Enabled;
  56. TAtomicBase Acquired;
  57. const TAtomicBase WakeLev;
  58. TAtomic Tokens_;
  59. /* This padd requires for align Tokens_ member on its own
  60. CPU cacheline. */
  61. ui64 padd_;
  62. };
  63. }