| 99 | std::thread thread; |
| 100 | |
| 101 | void timer_thread() { |
| 102 | ceph_pthread_setname("ceph_timer"); |
| 103 | std::unique_lock l(lock); |
| 104 | while (!suspended) { |
| 105 | auto now = TC::now(); |
| 106 | |
| 107 | while (!schedule.empty()) { |
| 108 | auto p = schedule.begin(); |
| 109 | // Should we wait for the future? |
| 110 | #if defined(_WIN32) |
| 111 | if (p->t - now > std::chrono::milliseconds(1)) { |
| 112 | // std::condition_variable::wait_for uses SleepConditionVariableSRW |
| 113 | // on Windows, which has millisecond precision. Deltas <1ms will |
| 114 | // lead to busy loops, which should be avoided. This situation is |
| 115 | // quite common since "wait_for" often returns ~1ms earlier than |
| 116 | // requested. |
| 117 | break; |
| 118 | } |
| 119 | #else // !_WIN32 |
| 120 | if (p->t > now) { |
| 121 | break; |
| 122 | } |
| 123 | #endif |
| 124 | |
| 125 | auto& e = *p; |
| 126 | schedule.erase(e); |
| 127 | events.erase(e.id); |
| 128 | |
| 129 | // Since we have only one thread it is impossible to have more |
| 130 | // than one running event |
| 131 | running = &e; |
| 132 | |
| 133 | l.unlock(); |
| 134 | p->f(); |
| 135 | l.lock(); |
| 136 | |
| 137 | if (running) { |
| 138 | running = nullptr; |
| 139 | delete &e; |
| 140 | } // Otherwise the event requeued itself |
| 141 | } |
| 142 | |
| 143 | if (suspended) |
| 144 | break; |
| 145 | if (schedule.empty()) { |
| 146 | cond.wait(l); |
| 147 | } else { |
| 148 | // Since wait_until takes its parameter by reference, passing |
| 149 | // the time /in the event/ is unsafe, as it might be canceled |
| 150 | // while we wait. |
| 151 | const auto t = schedule.begin()->t; |
| 152 | cond.wait_until(l, t); |
| 153 | } |
| 154 | } |
| 155 | } |
| 156 | |
| 157 | public: |
| 158 | timer() : suspended(false) { |
nothing calls this directly
no test coverage detected