HRESULT RIOSOCKAPI RIOSockInitialize()

in cpp/Riosock/Riosock.cpp [258:350]


HRESULT RIOSOCKAPI RIOSockInitialize()
{
    // Return if already initialized
    if (RIOSockRef > 0) {
        InterlockedIncrement(&RIOSockRef);
        return S_OK;
    }

    // Create lock for Completion Queue access
    CQAccessLock = new (std::nothrow) PrioritizedLock;
    if (nullptr == CQAccessLock) {
        return E_OUTOFMEMORY;
    }

    // Create IOCP handle for RECV CQ
    auto iocpHandleOfRecv = CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 0);
    if (iocpHandleOfRecv == nullptr)
    {
        DWORD errorCode = GetLastError();
        delete CQAccessLock;
        SetLastError(errorCode);
        return HRESULT_FROM_WIN32(errorCode);
    }

    // Create IOCP handle for SEND CQ
    auto iocpHandleOfSend = CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 0);
    if (iocpHandleOfSend == nullptr)
    {
        DWORD errorCode = GetLastError();
        // Close IOCP handle
        CloseHandle(iocpHandleOfRecv);
        delete CQAccessLock;
        SetLastError(errorCode);
        return HRESULT_FROM_WIN32(errorCode);
    }

    // Create OVERLAPPED
    auto overLapped = calloc(1, sizeof(OVERLAPPED));
    if (nullptr == overLapped) {
        // Close IOCP handle
        CloseHandle(iocpHandleOfRecv);
        CloseHandle(iocpHandleOfSend);
        delete CQAccessLock;
        SetLastError(WSAENOBUFS);
        return HRESULT_FROM_WIN32(WSAENOBUFS);
    }

    // With RIO, we don't associate the IOCP handle with the socket like 'typical' sockets
    // - Instead we directly pass the IOCP handle through RIOCreateCompletionQueue
    ::ZeroMemory(&RecvCompletionType, sizeof(RecvCompletionType));
    RecvCompletionType.Type = RIO_IOCP_COMPLETION;
    RecvCompletionType.Iocp.CompletionKey = reinterpret_cast<void*>(1);
    RecvCompletionType.Iocp.Overlapped = overLapped;
    RecvCompletionType.Iocp.IocpHandle = iocpHandleOfRecv;

    ::ZeroMemory(&SendCompletionType, sizeof(SendCompletionType));
    SendCompletionType.Type = RIO_IOCP_COMPLETION;
    SendCompletionType.Iocp.CompletionKey = reinterpret_cast<void*>(1);
    SendCompletionType.Iocp.Overlapped = overLapped;
    SendCompletionType.Iocp.IocpHandle = iocpHandleOfSend;
    
    // Create a completion queue for RECV
    RecvCQ = CreateRIOCompletionQueue(DefaultRIOCQSize, &RecvCompletionType);
    if (RIO_INVALID_CQ == RecvCQ) {
        DWORD errorCode = WSAGetLastError();
        CloseHandle(iocpHandleOfRecv);
        CloseHandle(iocpHandleOfSend);
        free(overLapped);
        delete CQAccessLock;
        SetLastError(errorCode);
        return HRESULT_FROM_WIN32(errorCode);
    }

    // Create a completion queue for SEND
    SendCQ = CreateRIOCompletionQueue(DefaultRIOCQSize, &SendCompletionType);
    if (RIO_INVALID_CQ == SendCQ) {
        DWORD errorCode = WSAGetLastError();
        CloseRIOCompletionQueue(RecvCQ);
        RecvCQ = RIO_INVALID_CQ;
        CloseHandle(iocpHandleOfRecv);
        CloseHandle(iocpHandleOfSend);
        free(overLapped);
        delete CQAccessLock;
        SetLastError(errorCode);
        return HRESULT_FROM_WIN32(errorCode);
    }

    // now that the CQ is created, update info
    CQSize = DefaultRIOCQSize;
    CQUsed = 0;

    return S_OK;
}