| 2512 | } |
| 2513 | |
| 2514 | static pn_event_batch_t *proactor_completion_loop(struct pn_proactor_t* p, bool can_block) { |
| 2515 | // Proact! Process inbound completions of async activity until one |
| 2516 | // of them provides a batch of events. |
| 2517 | while(true) { |
| 2518 | pn_event_batch_t *batch = NULL; |
| 2519 | |
| 2520 | DWORD win_timeout = can_block ? INFINITE : 0; |
| 2521 | DWORD num_xfer = 0; |
| 2522 | ULONG_PTR completion_key = 0; |
| 2523 | OVERLAPPED *overlapped = 0; |
| 2524 | |
| 2525 | bool good_op = GetQueuedCompletionStatus (p->iocp->completion_port, &num_xfer, |
| 2526 | &completion_key, &overlapped, win_timeout); |
| 2527 | if (!overlapped && !can_block && GetLastError() == WAIT_TIMEOUT) |
| 2528 | return NULL; // valid timeout |
| 2529 | |
| 2530 | if (!good_op && !overlapped) { |
| 2531 | // Should never happen. shutdown? |
| 2532 | // We aren't expecting a timeout, closed completion port, or other error here. |
| 2533 | PN_LOG_DEFAULT(PN_SUBSYSTEM_EVENT, PN_LEVEL_CRITICAL, "%s", errno_str("Windows Proton proactor internal failure\n", false).c_str()); |
| 2534 | abort(); |
| 2535 | } |
| 2536 | |
| 2537 | switch (completion_key) { |
| 2538 | case proactor_io: { |
| 2539 | // Normal IO case for connections and listeners |
| 2540 | iocp_result_t *result = (iocp_result_t *) overlapped; |
| 2541 | result->status = good_op ? 0 : GetLastError(); |
| 2542 | result->num_transferred = num_xfer; |
| 2543 | psocket_t *ps = (psocket_t *) result->iocpd->active_completer; |
| 2544 | batch = psocket_process(ps, result, p->reaper); |
| 2545 | break; |
| 2546 | } |
| 2547 | // completion_key on our completion port is always null unless set by us |
| 2548 | // in PostQueuedCompletionStatus. In which case, we hijack the overlapped |
| 2549 | // data structure for our own use. |
| 2550 | case psocket_wakeup_key: |
| 2551 | batch = psocket_process((psocket_t *) overlapped, NULL, p->reaper); |
| 2552 | break; |
| 2553 | case proactor_wake_key: |
| 2554 | batch = proactor_process((pn_proactor_t *) overlapped); |
| 2555 | break; |
| 2556 | case recycle_accept_key: |
| 2557 | recycle_result((accept_result_t *) overlapped); |
| 2558 | break; |
| 2559 | default: |
| 2560 | break; |
| 2561 | } |
| 2562 | if (batch) return batch; |
| 2563 | // No event generated. Try again with next completion. |
| 2564 | } |
| 2565 | } |
| 2566 | |
| 2567 | pn_event_batch_t *pn_proactor_wait(struct pn_proactor_t* p) { |
| 2568 | return proactor_completion_loop(p, true); |
no test coverage detected