cwindowssignalsfifoiocp

Which handle to pass to CreateIoCompletionPort, if using IOCP for basic signaling?


Background: As described in this article, Designing Applications for High Performance:

Consider using PostQueueCompletionStatus rather than SetEvent API. The latter boosts the target thread’s priority by 1 which may cause it to preempt something else.

I am working in C on Windows, and I'd like to replace signalling in a producer/consumer fifo from SetEvent/WaitForSingleObject to IO Completion Ports.

The reason is that I want the producer thread to be a background/low priority thread, but SetEvent always boosts the consumer thread and very often suspends my producer thread, which I would like to avoid to meet certain latency requirements.

Instrumentation for these methods show that I get delays in the order of ~50 microseconds in the producer thread every now and then, right after notifying the consumer thread using SetEvent, so if this is a cheap replacement I thought I might give it a try.

Short version: I want to switch something like this

void Produce(int some_item)
{
    Enqueue(some_item);
    SetEvent(hndEvent);
}

void Consume(void)
{
    while (true) 
    {
        if (WaitForSingleObject(hndEvent, INFINITE) == WAIT_OBJECT_0)
        {
            // consume
        }
    }
}

into something like this I guess:

void Produce(int some_item)
{
    Enqueue(some_item);

    unsigned long evt = 1; // "item enqueued"
    PostQueuedCompletionStatus(hndIOCP, 0, evt, NULL);
}

void Consume(void)
{
    while (true) 
    {
        unsigned long evt;
        LPOVERLAPPED ovlp;
        if (!GetQueuedCompletionStatus(hndIOCP, NULL, &evt, &ovlp, INFINITE))
            break;

        // consume
    }
}

But since I am not using this IOCP for anything other than signaling, what handle should I pass to CreateIoCompletionPort?

I thought I would simply do something like:

// single thread IOCP
hndIOCP = CreateIoCompletionPort(NULL, NULL, 0, 1);

but it just returns NULL.


Solution

  • I found the answer, I missed the following part in the documentation for CreateIoCompletionPort.

    The first parameter is FileHandle, and if not used it has to be set to INVALID_HANDLE_VALUE instead of zero.

    FileHandle [in]

    An open file handle or INVALID_HANDLE_VALUE.

    • The handle must be to an object that supports overlapped I/O.

    • If a handle is provided, it has to have been opened for overlapped I/O completion. For example, you must specify the FILE_FLAG_OVERLAPPED flag when using the CreateFile function to obtain the handle.

    • If INVALID_HANDLE_VALUE is specified, the function creates an I/O completion port without associating it with a file handle. In this case, the ExistingCompletionPort parameter must be NULL and the CompletionKey parameter is ignored.