| 162 | } |
| 163 | |
| 164 | void TContExecutor::WaitForIO() { |
| 165 | while (Ready_.Empty() && !WaitQueue_.Empty()) { |
| 166 | const auto now = Now(); |
| 167 | |
| 168 | // Waking a coroutine puts it into ReadyNext_ list |
| 169 | const auto next = WaitQueue_.WakeTimedout(now); |
| 170 | |
| 171 | if (!UserEvents_.Empty()) { |
| 172 | TIntrusiveList<IUserEvent> userEvents; |
| 173 | userEvents.Swap(UserEvents_); |
| 174 | do { |
| 175 | userEvents.PopFront()->Execute(); |
| 176 | } while (!userEvents.Empty()); |
| 177 | } |
| 178 | |
| 179 | // Polling will return as soon as there is an event to process or a timeout. |
| 180 | // If there are woken coroutines we do not want to sleep in the poller |
| 181 | // yet still we want to check for new io |
| 182 | // to prevent ourselves from locking out of io by constantly waking coroutines. |
| 183 | |
| 184 | if (ReadyNext_.Empty()) { |
| 185 | if (EnterPollerCallback_) { |
| 186 | EnterPollerCallback_->OnEnterPoller(); |
| 187 | } |
| 188 | Poll(next); |
| 189 | if (EnterPollerCallback_) { |
| 190 | EnterPollerCallback_->OnExitPoller(); |
| 191 | } |
| 192 | } else if (LastPoll_ + TDuration::MilliSeconds(5) < now) { |
| 193 | if (EnterPollerCallback_) { |
| 194 | EnterPollerCallback_->OnEnterPoller(); |
| 195 | } |
| 196 | Poll(now); |
| 197 | if (EnterPollerCallback_) { |
| 198 | EnterPollerCallback_->OnExitPoller(); |
| 199 | } |
| 200 | } |
| 201 | |
| 202 | Ready_.Append(ReadyNext_); |
| 203 | } |
| 204 | } |
| 205 | |
| 206 | void TContExecutor::Poll(TInstant deadline) { |
| 207 | Poller_.Wait(PollerEvents_, deadline); |
nothing calls this directly
no test coverage detected