// ====================================================================== // \title TokenBucket.cpp // \author vwong // \brief cpp file for a rate limiter utility class // // \copyright // // Copyright (C) 2009-2020 California Institute of Technology. // // ALL RIGHTS RESERVED. United States Government Sponsorship // acknowledged. // ====================================================================== #include namespace Utils { TokenBucket ::TokenBucket(U32 replenishInterval, U32 maxTokens, U32 replenishRate, U32 startTokens, Fw::Time startTime) : m_replenishInterval(replenishInterval), m_maxTokens(maxTokens), m_replenishRate(replenishRate), m_tokens(startTokens), m_time(startTime) {} TokenBucket ::TokenBucket(U32 replenishInterval, U32 maxTokens) : m_replenishInterval(replenishInterval), m_maxTokens(maxTokens), m_replenishRate(1), m_tokens(maxTokens), m_time(0, 0) { FW_ASSERT(this->m_maxTokens <= MAX_TOKEN_BUCKET_TOKENS, static_cast(this->m_maxTokens)); } void TokenBucket ::setReplenishInterval(U32 replenishInterval) { this->m_replenishInterval = replenishInterval; } void TokenBucket ::setMaxTokens(U32 maxTokens) { this->m_maxTokens = maxTokens; } void TokenBucket ::setReplenishRate(U32 replenishRate) { this->m_replenishRate = replenishRate; } void TokenBucket ::replenish() { if (this->m_tokens < this->m_maxTokens) { this->m_tokens = this->m_maxTokens; } } U32 TokenBucket ::getReplenishInterval() const { return this->m_replenishInterval; } U32 TokenBucket ::getMaxTokens() const { return this->m_maxTokens; } U32 TokenBucket ::getReplenishRate() const { return this->m_replenishRate; } U32 TokenBucket ::getTokens() const { return this->m_tokens; } bool TokenBucket ::trigger(const Fw::Time time) { // attempt replenishing if (this->m_replenishRate > 0) { Fw::Time replenishInterval = Fw::Time(this->m_replenishInterval / 1000000, this->m_replenishInterval % 1000000); Fw::Time nextTime = Fw::Time::add(this->m_time, replenishInterval); while (this->m_tokens < this->m_maxTokens && nextTime <= time) { // replenish by replenish rate, or up to maxTokens this->m_tokens += FW_MIN(this->m_replenishRate, this->m_maxTokens - this->m_tokens); this->m_time = nextTime; nextTime = Fw::Time::add(this->m_time, replenishInterval); } if (this->m_tokens >= this->m_maxTokens && this->m_time < time) { this->m_time = time; } } // attempt consuming token if (this->m_tokens > 0) { this->m_tokens--; return true; } else { return false; } } } // end namespace Utils