1

My main thread creates multiple I/O worker threads. I then initiate an I/O request from my main thread by doing:

{
    ...
    IoRequest *pIoRequest = new IoRequest(m_socket);
    pIoRequest->SetBuffer(vecCommandData); // vector of BYTEs
    pIoRequest->SetOperationType(OP_TYPE_SEND);
    WSASend(m_socket, pIoRequest->GetWsaBuffer(), 1, NULL, 0, pIoRequest, NULL);
    ...
}

At some point in one of my I/O worker threads, the request is completed and my IoRequest object's buffer is filled with valid response data.

DWORD WINAPI WorkerThreadProc(LPVOID lpParameter)
{
    IoCompletionPort *pIocp = reinterpret_cast<IoCompletionPort*>(lpParameter);    
    ...
    while (true)
    {
        BOOL bReturn = pIocp->GetStatus(&ulCompletionKey, &dwNumberOfBytesTransferred, (LPOVERLAPPED*)&pIoRequest);
        ...
        switch (pIoRequest->GetOperationType())
        {
        ...
        case OP_TYPE_RECEIVE_DATA:
            {
                ...
                // the requested I/O operation has completed and pIoRequest's buffer now contains valid response data!
                break;
            } 
        ...
        }
    }

    return 0;
}

How can I place my main thread in an alertable wait state after calling WSASend() and make it receive the response data whenever it's ready?

jpen
  • 2,129
  • 5
  • 32
  • 56
  • What other constraints are there on your main thread (i.e. do you need to pump messages while waiting, can you just block until a worker is ready, etc.)? – Nate Kohl Aug 06 '12 at 12:07
  • @Nate Kohl-Here is how I want my main thread to work; if there is already an I/O request being processed then my main thread just puts any further requests into a queue (rather than being blocked). Whenever the current request in progress has been completed, my main thread dequeues a pending request and send it using WSASend(). As a test, I’m calling while (1) { Sleep(1000); } for now after WSASend() immediately returns. – jpen Aug 06 '12 at 13:37

1 Answers1

2

In an IOCP server, it's typically GetQueuedCompletionStatus().

Martin James
  • 24,453
  • 3
  • 36
  • 60
  • 1
    If you're not using IOCP, then use [SleepEx](http://msdn.microsoft.com/en-us/library/windows/desktop/ms686307%28v=vs.85%29.aspx). – David Schwartz Aug 06 '12 at 12:24
  • @Martin James-I'm creating a client application that uses IOCP. My GetStatus() function internally calls GetQueuedCompletionStatus(). All my worker threads wait on the completion port by calling this function. What I'm after is a mechanism that allows my main thread to get notified whenever the request has been completed by the I/O worker threads. Maybe something like a callback function (OnResponseDataReceived() or something) implemented in my main thread that gets called upon every I/O request completion? …but I'm not sure how to do that. – jpen Aug 06 '12 at 13:17
  • @jpen - issue another WSArecv() for the next load of data and then PostMessage() the RxBuffer, (or whatever you call the class that represents an WSArecv() call and its data), instance to the main thread. If the RxBuffer class contains a reference to the socket object, (which it surely must do), then you must take the usual precautions if accessing the socket data from the main-thread message-handler while it's in use by IOCP work threads. – Martin James Aug 06 '12 at 13:58
  • @Martin James-Thanks but my application is not GUI-based so I don't have a "HWND hWnd" parameter to pass to PostMessage(). – jpen Aug 06 '12 at 14:10
  • OK, 'PostThreadmessage()'. Failing that, it's failrly easy to use a hidden window with the 'RegisterWindowClass()' and 'CreateWindow()' API's. A trivial WindProc could then process the messages though, with no GUI, what are you going to do with all the data? – Martin James Aug 06 '12 at 14:35
  • My application sends various commands to a networked device via LAN. The device responds by sending command specific response data back to the application. So basically I need to process that command specific data to see if each command was executed correctly, if not what error etc. – jpen Aug 06 '12 at 15:18
  • @Martin James-Thanks for the info. I'll give PostThreadMessage() a go. – jpen Aug 06 '12 at 15:31
  • @jpen: All the threads in your application are fundamentally the same. Whatever the main thread would do if you notified it can be done in another thread. (Absent some atypical restrictions.) – David Schwartz Aug 07 '12 at 03:16
  • @DavidSchwartz - I thought that too, but didn't want to confuse matters at this stage :) Maybe OP has some other reason for main-thread comms, (that's why I assumed 'GUI', as you probably guessed ). – Martin James Aug 07 '12 at 07:24