Optimus1
Optimus1

Reputation: 448

GetQueuedCompletionStatus - how to identify the “type” of the finished task?

Can you please tell me, when a ready task appears in the completion port queue, then retrieving it using the GetQueuedCompletionStatus function, how do you know if this ready task is for reading or writing?

Upvotes: 0

Views: 280

Answers (1)

Remy Lebeau
Remy Lebeau

Reputation: 597081

A common approach is to write a struct that either derives from the Win32 (WSA)OVERLAPPED struct, or has a (WSA)OVERLAPPED as its 1st data member. Then you can add other data members to your struct to identify its task, track its status, etc as needed.

You can then allocate an instance of your struct for each I/O operation, populating it as needed, and passing a pointer to it as an (WSA)OVERLAPPED* pointer to your chosen I/O function.

When the I/O completion comes back, you can typecast the provided OVERLAPPED* pointer into a pointer to your struct type to access its members.

For example:

enum MY_OP_TYPE { opReading, opWriting };

struct MY_STRUCT : OVERLAPPED // or WSAOVERLAPPED
{
    MY_OP_TYPE opType;
    // other data members as needed...

    MY_STRUCT()
    {
        Internal = 0;
        InternalHigh = 0;
        Offset = 0;
        OffsetHigh = 0;
        hEvent = NULL;
        // other initializations as needed...
    }

    ~MY_STRUCT()
    {
        // cleanups as needed...
        // free hEvent if it is a (WSA)Event object...
    }

    // other methods as needed...
};
MY_STRUCT *ms = new MY_STRUCT;
ms->opType = opReading;
ms->hEvent = ...; // depending on which I/O function you are using, this could be a (WSA)Event object, or a pointer to opaque app data, etc...
// other assignments as needed...
...

if (IoReadingFunction(..., static_cast<OVERLAPPED*>(ms), ...) == FALSE /* or SOCKET_ERROR */)
{
    if (GetLastError() != ERROR_IO_PENDING)
    // or
    // if (WSAGetLastError() != WSA_IO_PENDING) 
    {
        ...
        delete ms;
    }
}
...
OVERLAPPED *ov;
...

GetQueuedCompletionStatus(..., &ov, ... );
if (ov)
{
    MY_STRUCT *ms = static_cast<MY_STRUCT*>(ov);
    // use ms as needed...

    switch (ms->opType)
    {
        ...
    }

    ...

    delete ms;
}

Upvotes: 3

Related Questions