//=========================================================================== void RioDispatchThread::onTask () { static const int kNumResults = 100; RIORESULT results[kNumResults]; ITaskNotify * tasks[size(results)]; int count; for (;;) { unique_lock<mutex> lk{s_mut}; if (s_mode == kRunStopping) { s_mode = kRunStopped; break; } count = s_rio.RIODequeueCompletion( s_cq, results, (ULONG) size(results) ); if (count == RIO_CORRUPT_CQ) logMsgCrash() << "RIODequeueCompletion: " << WinError{}; for (int i = 0; i < count; ++i) { auto&& rr = results[i]; auto task = (SocketRequestTaskBase *) rr.RequestContext; task->m_socket = (SocketBase *) rr.SocketContext; task->m_xferError = (WinError::NtStatus) rr.Status; task->m_xferBytes = rr.BytesTransferred; tasks[i] = task; } if (int error = s_rio.RIONotify(s_cq)) logMsgCrash() << "RIONotify: " << WinError{}; lk.unlock(); if (count) taskPushEvent(tasks, count); s_cqReady.wait(); } s_modeCv.notify_one(); }
unsigned int __stdcall IOThread(void *pV) { DWORD numberOfBytes = 0; ULONG_PTR completionKey = 0; OVERLAPPED* pOverlapped = 0; RIORESULT results[RIO_MAX_RESULTS]; while (true) { if (!::GetQueuedCompletionStatus(g_hIOCP, &numberOfBytes, &completionKey, &pOverlapped, INFINITE)) { printf_s("GetQueuedCompletionStatus Error: %d\n", GetLastError()); exit(0); } /// exit when CK_STOP if (completionKey == CK_STOP) break; memset(results, 0, sizeof(results)); ULONG numResults = g_rio.RIODequeueCompletion(g_completionQueue, results, RIO_MAX_RESULTS); if (0 == numResults || RIO_CORRUPT_CQ == numResults) { printf_s("RIODequeueCompletion Error: %d\n", GetLastError()); exit(0); } /// Notify after Dequeueing INT notifyResult = g_rio.RIONotify(g_completionQueue); if (notifyResult != ERROR_SUCCESS) { printf_s("RIONotify Error: %d\n", GetLastError()); exit(0); } for (DWORD i = 0; i < numResults; ++i) { EXTENDED_RIO_BUF* pBuffer = reinterpret_cast<EXTENDED_RIO_BUF*>(results[i].RequestContext); if (OP_RECV == pBuffer->operation) { /// error when total packet is not arrived because this is UDP if (results[i].BytesTransferred != RECV_BUFFER_SIZE) break; ///// ECHO TEST const char* offset = g_recvBufferPointer + pBuffer->Offset; /// RQ is not thread-safe (need to be optimized...) ::EnterCriticalSection(&g_criticalSection); { EXTENDED_RIO_BUF* sendBuf = &(g_sendRioBufs[g_sendRioBufIndex++ % g_sendRioBufTotalCount]); char* sendOffset = g_sendBufferPointer + sendBuf->Offset; memcpy_s(sendOffset, RECV_BUFFER_SIZE, offset, pBuffer->Length); if (!g_rio.RIOSendEx(g_requestQueue, sendBuf, 1, NULL, &g_addrRioBufs[g_addrRioBufIndex % g_addrRioBufTotalCount], NULL, NULL, 0, sendBuf)) { printf_s("RIOSend Error: %d\n", GetLastError()); exit(0); } } ::LeaveCriticalSection(&g_criticalSection); } else if (OP_SEND == pBuffer->operation) { /// RQ is not thread-safe ::EnterCriticalSection(&g_criticalSection); { if (!g_rio.RIOReceiveEx(g_requestQueue, pBuffer, 1, NULL, &g_addrRioBufs[g_addrRioBufIndex % g_addrRioBufTotalCount], NULL, 0, 0, pBuffer)) { printf_s("RIOReceive Error: %d\n", GetLastError()); exit(0);; } g_addrRioBufIndex++; } ::LeaveCriticalSection(&g_criticalSection); } else break; } } return 0; }