KKlouzal
KKlouzal

Reputation: 722

Dequeuing Multiple Completions With GetQueuedCompletionStatusEx

I'm attempting to use GetQueuedCompletionStatusEx to dequeue multiple completions from an I/O Completion Port (IOCP).

void GetPackets() {
    OVERLAPPED_ENTRY pEntries;
    ULONG NumEntries;
    if (!GetQueuedCompletionStatusEx(PointIOCP, &pEntries, PENDING_RECVS, &NumEntries, 0, false)) {
        printf("Get Queued Completion Status - Point Error: %i\n", GetLastError());
        return;
    }

    if (NumEntries = 0) { return; }

    printf("Got Entries!\n");
    for (unsigned int i = 0; i < NumEntries; i++) {
        NetPacket_Recv* Packet = reinterpret_cast<NetPacket_Recv*>(pEntries[i].lpOverlapped);
    }
}

The error is with pEntries[i].lpOverlapped. The compiler is telling me no [] operator exists for OVERLAPPED_ENTRY. According to the documentation pEntries should receive an array of OVERLAPPED_ENTRY structures.

lpCompletionPortEntries: Receives an array of OVERLAPPED_ENTRY structures that hold the entries.

I'm only declaring a single instance of OVERLAPPED_ENTRY when I define pEntries. How do I define pEntries to be a pointer to an array of OVERLAPPED_ENTRY instead?

Upvotes: 0

Views: 421

Answers (2)

Remy Lebeau
Remy Lebeau

Reputation: 597081

You quoted from the documentation, but you seem to have missed the important part above the snippet you quoted:

lpCompletionPortEntries [out]

On input, points to a pre-allocated array of OVERLAPPED_ENTRY structures.

On output, receives an array of OVERLAPPED_ENTRY structures that hold the entries. The number of array elements is provided by ulNumEntriesRemoved.

OVERLAPPED_ENTRY pEntries; declares a single OVERLAPPED_ENTRY, not an array of OVERLAPPED_ENTRY elements. That is why pEntries[i] does not work, because pEntries is not an array (or even a pointer).

When you pass &pEntries to the function, you are passing in a pointer to 1 OVERLAPPED_ENTRY, but you are setting the ulCount pointer to PENDING_RECVS, so the function is expecting you to pass in a pointer to an array containing at last PENDING_RECVS number of OVERLAPPED_ENTRY elements in it. You are not doing that (unless PENDING_RECVS is 1).

Also, NumEntries = 0 is an assignment, not a comparison. You should have gotten a compiler warning about that. You need to use operator== instead of operator=.

Try something more like this instead:

void GetPackets() {
    OVERLAPPED_ENTRY Entries[PENDING_RECVS];
    ULONG NumEntries = 0;
    if (!GetQueuedCompletionStatusEx(PointIOCP, Entries, PENDING_RECVS, &NumEntries, 0, FALSE)) {
        printf("Get Queued Completion Status - Point Error: %u\n", GetLastError());
        return;
    }

    if (NumEntries == 0) { return; }

    printf("Got Entries!\n");
    for (ULONG i = 0; i < NumEntries; ++i) {
        NetPacket_Recv* Packet = reinterpret_cast<NetPacket_Recv*>(Entries[i].lpOverlapped);
        ...
    }
}

Upvotes: 1

SoronelHaetir
SoronelHaetir

Reputation: 15172

Make it:

OVERLAPPED_ENTRY entries[10];

(or some other maximum number you would like to return) instead, just like any other array. And pass the number of instances as the third parameter to GetQueuedCompletionStatusEx. (note how I changed the variable name as it is not actually a pointer). The function parameter is a pointer but the array variable is not.

Upvotes: 1

Related Questions