| 276 | } |
| 277 | |
| 278 | T dequeue() final { |
| 279 | ceph_assert(!empty()); |
| 280 | |
| 281 | if (!(high_queue.empty())) { |
| 282 | T ret = std::move(high_queue.rbegin()->second.front().second); |
| 283 | high_queue.rbegin()->second.pop_front(); |
| 284 | if (high_queue.rbegin()->second.empty()) { |
| 285 | high_queue.erase(high_queue.rbegin()->first); |
| 286 | } |
| 287 | return ret; |
| 288 | } |
| 289 | |
| 290 | // if there are multiple buckets/subqueues with sufficient tokens, |
| 291 | // we behave like a strict priority queue among all subqueues that |
| 292 | // are eligible to run. |
| 293 | for (typename SubQueues::iterator i = queue.begin(); |
| 294 | i != queue.end(); |
| 295 | ++i) { |
| 296 | ceph_assert(!(i->second.empty())); |
| 297 | if (i->second.front().first < i->second.num_tokens()) { |
| 298 | unsigned cost = i->second.front().first; |
| 299 | i->second.take_tokens(cost); |
| 300 | T ret = std::move(i->second.front().second); |
| 301 | i->second.pop_front(); |
| 302 | if (i->second.empty()) { |
| 303 | remove_queue(i->first); |
| 304 | } |
| 305 | distribute_tokens(cost); |
| 306 | return ret; |
| 307 | } |
| 308 | } |
| 309 | |
| 310 | // if no subqueues have sufficient tokens, we behave like a strict |
| 311 | // priority queue. |
| 312 | unsigned cost = queue.rbegin()->second.front().first; |
| 313 | T ret = std::move(queue.rbegin()->second.front().second); |
| 314 | queue.rbegin()->second.pop_front(); |
| 315 | if (queue.rbegin()->second.empty()) { |
| 316 | remove_queue(queue.rbegin()->first); |
| 317 | } |
| 318 | distribute_tokens(cost); |
| 319 | return ret; |
| 320 | } |
| 321 | |
| 322 | void dump(ceph::Formatter *f) const final { |
| 323 | f->dump_int("total_priority", total_priority); |
nothing calls this directly
no test coverage detected