Function to handle all IOCP notifications. Returns true if the IOCP loop should continue and false if it should stop.
| 228 | // Function to handle all IOCP notifications. Returns true if the IOCP loop |
| 229 | // should continue and false if it should stop. |
| 230 | static bool check_and_handle_completion(const OVERLAPPED_ENTRY& entry) |
| 231 | { |
| 232 | switch (entry.lpCompletionKey) { |
| 233 | case KEY_QUIT: { |
| 234 | return false; |
| 235 | } |
| 236 | case KEY_TIMER: { |
| 237 | // In the IOCP, we just set the timer. When the timer completes, it will |
| 238 | // queue up an APC that will interrupt the IOCP loop in order to execute |
| 239 | // the APC callback. |
| 240 | TimerOverlapped* timer = |
| 241 | reinterpret_cast<TimerOverlapped*>(entry.lpOverlapped); |
| 242 | |
| 243 | const BOOL success = ::SetWaitableTimer( |
| 244 | timer->timer, &timer->time, 0, &timer_apc, timer, TRUE); |
| 245 | |
| 246 | if (!success) { |
| 247 | // Nothing we can really do here aside from log the event. |
| 248 | std::string errorMsg = WindowsError().message; |
| 249 | LOG(FATAL) |
| 250 | << "process::windows::handle_completion failed to set timer: " |
| 251 | << errorMsg; |
| 252 | } |
| 253 | return true; |
| 254 | } |
| 255 | case KEY_IO: { |
| 256 | if (entry.lpOverlapped == nullptr) { |
| 257 | // Don't know if this is possible, but just log it in case. |
| 258 | LOG(FATAL) << "process::windows::handle_completion returned with a null" |
| 259 | << "overlapped object"; |
| 260 | } else { |
| 261 | handle_io(entry.lpOverlapped, entry.dwNumberOfBytesTransferred); |
| 262 | } |
| 263 | return true; |
| 264 | } |
| 265 | } |
| 266 | |
| 267 | UNREACHABLE(); |
| 268 | } |
| 269 | |
| 270 | |
| 271 | // Windows Event loop implementation. |