blob: 5a3161ae9cdfb16dc2c669d86bdf4c428f7b5b89 (
plain) (
tree)
|
|
#pragma once
#include <library/cpp/deprecated/atomic/atomic.h>
namespace NBus {
/* Consumer and feeder quota model impl.
Consumer thread only calls:
Acquire(), fetches tokens for usage from bucket;
Consume(), eats given amount of tokens, must not
be greater than Value() items;
Other threads (feeders) calls:
Return(), put used tokens back to bucket;
*/
class TTokenQuota {
public:
TTokenQuota(bool enabled, size_t tokens, size_t wake)
: Enabled(tokens > 0 ? enabled : false)
, Acquired(0)
, WakeLev(wake < 1 ? Max<size_t>(1, tokens / 2) : 0)
, Tokens_(tokens)
{
Y_UNUSED(padd_);
}
bool Acquire(TAtomicBase level = 1, bool force = false) {
level = Max(TAtomicBase(level), TAtomicBase(1));
if (Enabled && (Acquired < level || force)) {
Acquired += AtomicSwap(&Tokens_, 0);
}
return !Enabled || Acquired >= level;
}
void Consume(size_t items) {
if (Enabled) {
Y_ASSERT(Acquired >= TAtomicBase(items));
Acquired -= items;
}
}
bool Return(size_t items_) noexcept {
if (!Enabled || items_ == 0)
return false;
const TAtomic items = items_;
const TAtomic value = AtomicAdd(Tokens_, items);
return (value - items < WakeLev && value >= WakeLev);
}
bool IsEnabled() const noexcept {
return Enabled;
}
bool IsAboveWake() const noexcept {
return !Enabled || (WakeLev <= AtomicGet(Tokens_));
}
size_t Tokens() const noexcept {
return Acquired + AtomicGet(Tokens_);
}
size_t Check(const TAtomicBase level) const noexcept {
return !Enabled || level <= Acquired;
}
private:
bool Enabled;
TAtomicBase Acquired;
const TAtomicBase WakeLev;
TAtomic Tokens_;
/* This padd requires for align Tokens_ member on its own
CPU cacheline. */
ui64 padd_;
};
}
|