| 496 | } |
| 497 | |
| 498 | void container::impl::run_timer_jobs() { |
| 499 | timestamp now = timestamp::now(); |
| 500 | std::vector<scheduled> tasks; |
| 501 | |
| 502 | // We first extract all the runnable tasks and then run them - this is to avoid having tasks |
| 503 | // injected as we are running them (which could potentially never end) |
| 504 | { |
| 505 | GUARD(deferred_lock_); |
| 506 | |
| 507 | // Figure out how many tasks we need to execute and pop them to the back of the |
| 508 | // queue (in reverse order) |
| 509 | unsigned i = 0; |
| 510 | for (;;) { |
| 511 | // Have we seen all the queued tasks? |
| 512 | if ( deferred_.size()-i==0 ) break; |
| 513 | |
| 514 | // Is the next task in the future? |
| 515 | timestamp next_time = deferred_.front().time; |
| 516 | if ( next_time>now ) { |
| 517 | pn_proactor_set_timeout(proactor_, (next_time-now).milliseconds()); |
| 518 | break; |
| 519 | } |
| 520 | |
| 521 | std::pop_heap(deferred_.begin(), deferred_.end()-i); |
| 522 | ++i; |
| 523 | } |
| 524 | // Nothing to do |
| 525 | if ( i==0 ) return; |
| 526 | |
| 527 | // Now we know how many tasks to run |
| 528 | if ( deferred_.size()==i ) { |
| 529 | // If we sorted the entire heap, then we're executing every task |
| 530 | // so don't need to copy and can just swap |
| 531 | tasks.swap(deferred_); |
| 532 | } else { |
| 533 | // Otherwise just copy the ones we sorted |
| 534 | tasks = std::vector<scheduled>(deferred_.end()-i, deferred_.end()); |
| 535 | |
| 536 | // Remove tasks to be executed |
| 537 | deferred_.resize(deferred_.size()-i); |
| 538 | } |
| 539 | } |
| 540 | // We've now taken the tasks to run from the deferred tasks |
| 541 | // so we can run them unlocked |
| 542 | // NB. We copied the due tasks in reverse order so execute from end |
| 543 | |
| 544 | for (int i = tasks.size()-1; i>=0; --i) { |
| 545 | const auto& task = tasks[i]; |
| 546 | bool active; |
| 547 | |
| 548 | { |
| 549 | GUARD(deferred_lock_); |
| 550 | // NB. erase returns the number of items erased |
| 551 | active = is_active_.erase(task.w_handle); |
| 552 | } |
| 553 | if (active) { |
| 554 | task.task(); |
| 555 | } |
nothing calls this directly
no test coverage detected