throttle类用来限制资源数量,主要提供两个成员get/put函数用于操作资源。其源码实现在src/common/throttle.cc中
首先看看其构造函数
Throttle::Throttle(CephContext *cct, const std::string& n, int64_t m,
bool _use_perf)
: cct(cct), name(n), max(m), use_perf(_use_perf)
{
assert(m >= 0);
#如果用户不用debug 的话,活设置user_perf 为零,这里就退出了,所以构造函数啥也没有做
if (!use_perf)
return;
if (cct->_conf->throttler_perf_counter) {
PerfCountersBuilder b(cct, string("throttle-") + name, l_throttle_first, l_throttle_last);
b.add_u64(l_throttle_val, "val", "Currently available throttle");
}
}
其次当获取资源时候会调用get函数
bool Throttle::get(int64_t c, int64_t m)
{
#资源最大值如果是零肯定就无法获取资源其次如果要获取的资源也是零,就退出,很明显这两种
#是异常case
if (0 == max && 0 == m) {
return false;
}
assert(c >= 0);
ldout(cct, 10) << "get " << c << " (" << count.load() << " -> " << (count.load() + c) << ")" << dendl;
if (logger) {
logger->inc(l_throttle_get_started);
}
bool waited = false;
{
#定义锁,这里也可以看出get函数可以用在多线程的环境中
auto l = uniquely_lock(lock);
if (m) {
assert(m > 0);
_reset_max(m);
}
#看出是否获取资源个数c时是否需要等待
waited = _wait(c, l);
#记录已经消耗的资源数
count += c;
}
return waited;
}
继续看看_wait的实现
bool Throttle::_wait(int64_t c, UNIQUE_LOCK_T(lock)& l)
{
mono_time start;
bool waited = false;
#核心是通过should_wait来判断是否需要等待,如果资源还够本次分配的话,这个if条件就不成立
#整个wait函数就返回了
if (_should_wait(c) || !conds.empty()) { // always wait behind other waiters.
{
#新建一个cons
auto cv = conds.emplace(conds.end());
auto w = make_scope_guard([this, cv]() {
conds.erase(cv);
});
waited = true;
ldout(cct, 2) << "_wait waiting..." << dendl;
if (logger)
start = mono_clock::now();
#荣光cond的wait函数还等待。直到在put函数中调用 conds.front().notify_one()才结束等待
cv->wait(l, [this, c, cv]() { return (!_should_wait(c) &&
cv == conds.begin()); });
}
}
// wake up the next guy
if (!conds.empty())
conds.front().notify_one();
}
return waited;
}
我们在看看如果判断是否要等待
bool _should_wait(int64_t c) const {
int64_t m = max;
int64_t cur = count;
return
m &&
((c <= m && cur + c > m) || // normally stay under max
(c >= m && cur > m)); // except for large c
}
从这里可以看出只要需要申请的资源c小于资源的最大值且c加上已经申请的cur还小于最大值m就不用等待否则就需要等待别人通过put函数释放资源
最后我们在看看put函数是如果释放资源的
int64_t Throttle::put(int64_t c)
{
#如果最大值是零就没啥好释放的,直接退出
if (0 == max) {
return 0;
}
#断言要释放的资源c必须大于零
assert(c >= 0);
ldout(cct, 10) << "put " << c << " (" << count.load() << " -> "
<< (count.load()-c) << ")" << dendl;
auto l = uniquely_lock(lock);
if (c) {
#检查是否有conds在等待,如果有的话,则发出通过
if (!conds.empty())
conds.front().notify_one();
// if count goes negative, we failed somewhere!
assert(static_cast<int64_t>(count) >= c);
#已经占用的资源减去要释放的资源c
count -= c;
}
return count;
}
ceph中的Throttle类
最新推荐文章于 2023-06-15 22:48:19 发布