blob: 8e0d35841ecba03cba87381071f4ddc5131d44e6 [file] [log] [blame]
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "remoting/base/leaky_bucket.h"
namespace remoting {
LeakyBucket::LeakyBucket(int depth, int rate)
: depth_(depth),
rate_(rate),
current_level_(0),
level_updated_time_(base::TimeTicks::Now()) {}
LeakyBucket::~LeakyBucket() = default;
bool LeakyBucket::RefillOrSpill(int drops, base::TimeTicks now) {
UpdateLevel(now);
int new_level = current_level_ + drops;
if (depth_ >= 0 && new_level > depth_) {
return false;
}
current_level_ = new_level;
return true;
}
base::TimeTicks LeakyBucket::GetEmptyTime() {
// To avoid unnecessary complexity in the consuming class, we return a fairly
// large value (1 minute) here if the b/w estimate is 0 which means that the
// consumer does not need to handle overflow issues caused by returning
// TimeDelta::Max().
base::TimeDelta time_to_empty =
(rate_ != 0)
? base::Microseconds(base::TimeTicks::kMicrosecondsPerSecond *
current_level_ / rate_)
: base::Minutes(1);
return level_updated_time_ + time_to_empty;
}
void LeakyBucket::UpdateRate(int new_rate, base::TimeTicks now) {
UpdateLevel(now);
rate_ = new_rate;
}
void LeakyBucket::UpdateLevel(base::TimeTicks now) {
int64_t drainage_amount = rate_ *
(now - level_updated_time_).InMicroseconds() /
base::TimeTicks::kMicrosecondsPerSecond;
if (current_level_ < drainage_amount) {
current_level_ = 0;
} else {
current_level_ -= drainage_amount;
}
level_updated_time_ = now;
}
} // namespace remoting