| 286 | {} |
| 287 | |
| 288 | Try<Nothing> EventLoop::run() |
| 289 | { |
| 290 | const Try<long> maxEntries = os::cpus(); |
| 291 | if (maxEntries.isError()) { |
| 292 | return Error(maxEntries.error()); |
| 293 | } |
| 294 | |
| 295 | bool loop = true; |
| 296 | std::vector<OVERLAPPED_ENTRY> entries(maxEntries.get()); |
| 297 | while (loop) { |
| 298 | ULONG dequeued_entries; |
| 299 | |
| 300 | // This function can return in three ways: |
| 301 | // 1) We get some IO completion events and the function will return true. |
| 302 | // 2) A timer APC interrupts the function in its alertable wait status, |
| 303 | // so the thread will execute the APC. The function will return false |
| 304 | // and set the error to `WAIT_IO_COMPLETION`. |
| 305 | // 3) We get a legitimate error, so we exit early. |
| 306 | BOOL success = ::GetQueuedCompletionStatusEx( |
| 307 | iocp_handle_.get(), |
| 308 | entries.data(), |
| 309 | maxEntries.get(), |
| 310 | &dequeued_entries, |
| 311 | INFINITE, |
| 312 | TRUE); |
| 313 | |
| 314 | if (!success) { |
| 315 | // Case 2: Got APC interrupt. We simply continue the loop. |
| 316 | if (::GetLastError() == WAIT_IO_COMPLETION) { |
| 317 | continue; |
| 318 | } |
| 319 | |
| 320 | // We hit case 3, which means we got a serious error. |
| 321 | return WindowsError(); |
| 322 | } |
| 323 | |
| 324 | // Case 1: Dequeue completion packets and process them. If we get a quit |
| 325 | // notification, then we will finish the current queue and then exit. |
| 326 | for (ULONG i = 0; i < dequeued_entries; i++) { |
| 327 | const bool continue_loop = check_and_handle_completion(entries[i]); |
| 328 | loop = loop && continue_loop; |
| 329 | } |
| 330 | } |
| 331 | return Nothing(); |
| 332 | } |
| 333 | |
| 334 | |
| 335 | Try<Nothing> EventLoop::stop() |
nothing calls this directly
no test coverage detected