// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
// vim: ts=8 sw=2 smarttab
+#include "include/scope_guard.h"
+
#include "common/Throttle.h"
#include "common/perf_counters.h"
Throttle::~Throttle()
{
- while (!cond.empty()) {
- Cond *cv = cond.front();
- delete cv;
- cond.pop_front();
+ {
+ Mutex::Locker l(lock);
+ assert(cond.empty());
}
if (!use_perf)
utime_t start;
bool waited = false;
if (_should_wait(c) || !cond.empty()) { // always wait behind other waiters.
- Cond *cv = new Cond;
- cond.push_back(cv);
- waited = true;
- ldout(cct, 2) << "_wait waiting..." << dendl;
- if (logger)
- start = ceph_clock_now();
-
- do {
- cv->Wait(lock);
- } while (_should_wait(c) || cv != cond.front());
-
- ldout(cct, 2) << "_wait finished waiting" << dendl;
- if (logger) {
- utime_t dur = ceph_clock_now() - start;
- logger->tinc(l_throttle_wait, dur);
+ {
+ auto cv = cond.insert(cond.end(), new Cond);
+ auto w = make_scope_guard([this, cv]() {
+ delete *cv;
+ cond.erase(cv);
+ });
+ waited = true;
+ ldout(cct, 2) << "_wait waiting..." << dendl;
+ if (logger)
+ start = ceph_clock_now();
+
+ do {
+ (*cv)->Wait(lock);
+ } while ((_should_wait(c) || cv != cond.begin()));
+
+ ldout(cct, 2) << "_wait finished waiting" << dendl;
+ if (logger) {
+ utime_t dur = ceph_clock_now() - start;
+ logger->tinc(l_throttle_wait, dur);
+ }
}
-
- delete cv;
- cond.pop_front();
-
// wake up the next guy
if (!cond.empty())
cond.front()->SignalOne();
BackoffThrottle::~BackoffThrottle()
{
+ {
+ locker l(lock);
+ assert(waiters.empty());
+ }
+
if (!use_perf)
return;
{
Mutex::Locker l(m_lock);
assert(m_current == 0);
+ assert(waiters == 0);
}
void SimpleThrottle::start_op()
{
Mutex::Locker l(m_lock);
- while (m_max == m_current)
+ while (m_max == m_current) {
+ waiters++;
m_cond.Wait(m_lock);
+ waiters--;
+ }
++m_current;
}
int SimpleThrottle::wait_for_ret()
{
Mutex::Locker l(m_lock);
- while (m_current > 0)
+ while (m_current > 0) {
+ waiters++;
m_cond.Wait(m_lock);
+ waiters--;
+ }
return m_ret;
}
m_ignore_enoent(ignore_enoent), m_next_tid(0), m_complete_tid(0) {
}
+OrderedThrottle::~OrderedThrottle() {
+ Mutex::Locker locker(m_lock);
+ assert(waiters == 0);
+}
+
C_OrderedThrottle *OrderedThrottle::start_op(Context *on_finish) {
assert(on_finish != NULL);
complete_pending_ops();
while (m_max == m_current) {
+ ++waiters;
m_cond.Wait(m_lock);
+ --waiters;
complete_pending_ops();
}
++m_current;
complete_pending_ops();
while (m_current > 0) {
+ ++waiters;
m_cond.Wait(m_lock);
+ --waiters;
complete_pending_ops();
}
return m_ret_val;