mirror of
https://github.com/ceph/ceph
synced 2024-12-24 04:14:07 +00:00
common/Finisher: simplify
The second _rval list was a dumb idea. A vector of pairs is simpler and more efficient. Also, extend support to any container type. Signed-off-by: Sage Weil <sage@redhat.com>
This commit is contained in:
parent
da7d071654
commit
f46efeb47c
src/common
@ -50,11 +50,10 @@ void *Finisher::finisher_thread_entry()
|
||||
/// Every time we are woken up, we process the queue until it is empty.
|
||||
while (!finisher_queue.empty()) {
|
||||
// To reduce lock contention, we swap out the queue to process.
|
||||
// This way other threads can submit new contexts to complete while we are working.
|
||||
vector<Context*> ls;
|
||||
list<pair<Context*,int> > ls_rval;
|
||||
// This way other threads can submit new contexts to complete
|
||||
// while we are working.
|
||||
vector<pair<Context*,int>> ls;
|
||||
ls.swap(finisher_queue);
|
||||
ls_rval.swap(finisher_queue_rval);
|
||||
finisher_running = true;
|
||||
finisher_lock.Unlock();
|
||||
ldout(cct, 10) << "finisher_thread doing " << ls << dendl;
|
||||
@ -65,21 +64,8 @@ void *Finisher::finisher_thread_entry()
|
||||
}
|
||||
|
||||
// Now actually process the contexts.
|
||||
for (vector<Context*>::iterator p = ls.begin();
|
||||
p != ls.end();
|
||||
++p) {
|
||||
if (*p) {
|
||||
(*p)->complete(0);
|
||||
} else {
|
||||
// When an item is NULL in the finisher_queue, it means
|
||||
// we should instead process an item from finisher_queue_rval,
|
||||
// which has a parameter for complete() other than zero.
|
||||
// This preserves the order while saving some storage.
|
||||
assert(!ls_rval.empty());
|
||||
Context *c = ls_rval.front().first;
|
||||
c->complete(ls_rval.front().second);
|
||||
ls_rval.pop_front();
|
||||
}
|
||||
for (auto p : ls) {
|
||||
p.first->complete(p.second);
|
||||
}
|
||||
ldout(cct, 10) << "finisher_thread done with " << ls << dendl;
|
||||
ls.clear();
|
||||
|
@ -42,17 +42,12 @@ class Finisher {
|
||||
bool finisher_stop; ///< Set when the finisher should stop.
|
||||
bool finisher_running; ///< True when the finisher is currently executing contexts.
|
||||
bool finisher_empty_wait; ///< True mean someone wait finisher empty.
|
||||
|
||||
/// Queue for contexts for which complete(0) will be called.
|
||||
/// NULLs in this queue indicate that an item from finisher_queue_rval
|
||||
/// should be completed in that place instead.
|
||||
vector<Context*> finisher_queue;
|
||||
vector<pair<Context*,int>> finisher_queue;
|
||||
|
||||
string thread_name;
|
||||
|
||||
/// Queue for contexts for which the complete function will be called
|
||||
/// with a parameter other than 0.
|
||||
list<pair<Context*,int> > finisher_queue_rval;
|
||||
|
||||
/// Performance counter for the finisher's queue length.
|
||||
/// Only active for named finishers.
|
||||
PerfCounters *logger;
|
||||
@ -72,21 +67,20 @@ class Finisher {
|
||||
if (finisher_queue.empty()) {
|
||||
finisher_cond.Signal();
|
||||
}
|
||||
if (r) {
|
||||
finisher_queue_rval.push_back(pair<Context*, int>(c, r));
|
||||
finisher_queue.push_back(NULL);
|
||||
} else
|
||||
finisher_queue.push_back(c);
|
||||
finisher_queue.push_back(make_pair(c, r));
|
||||
if (logger)
|
||||
logger->inc(l_finisher_queue_len);
|
||||
finisher_lock.Unlock();
|
||||
}
|
||||
void queue(vector<Context*>& ls) {
|
||||
|
||||
void queue(list<Context*>& ls) {
|
||||
finisher_lock.Lock();
|
||||
if (finisher_queue.empty()) {
|
||||
finisher_cond.Signal();
|
||||
}
|
||||
finisher_queue.insert(finisher_queue.end(), ls.begin(), ls.end());
|
||||
for (auto i : ls) {
|
||||
finisher_queue.push_back(make_pair(i, 0));
|
||||
}
|
||||
if (logger)
|
||||
logger->inc(l_finisher_queue_len, ls.size());
|
||||
finisher_lock.Unlock();
|
||||
@ -97,18 +91,22 @@ class Finisher {
|
||||
if (finisher_queue.empty()) {
|
||||
finisher_cond.Signal();
|
||||
}
|
||||
finisher_queue.insert(finisher_queue.end(), ls.begin(), ls.end());
|
||||
for (auto i : ls) {
|
||||
finisher_queue.push_back(make_pair(i, 0));
|
||||
}
|
||||
if (logger)
|
||||
logger->inc(l_finisher_queue_len, ls.size());
|
||||
finisher_lock.Unlock();
|
||||
ls.clear();
|
||||
}
|
||||
void queue(list<Context*>& ls) {
|
||||
void queue(vector<Context*>& ls) {
|
||||
finisher_lock.Lock();
|
||||
if (finisher_queue.empty()) {
|
||||
finisher_cond.Signal();
|
||||
}
|
||||
finisher_queue.insert(finisher_queue.end(), ls.begin(), ls.end());
|
||||
for (auto i : ls) {
|
||||
finisher_queue.push_back(make_pair(i, 0));
|
||||
}
|
||||
if (logger)
|
||||
logger->inc(l_finisher_queue_len, ls.size());
|
||||
finisher_lock.Unlock();
|
||||
|
Loading…
Reference in New Issue
Block a user