// thread worker function (if it returns true, thread will continue running)
bool TCPIocpThread::run (float _dtInSeconds)
{
TCPSocketIocp* iocp_socket;
// 1st parameter is the value we passed when creating the completion port
// so we can cast the dword pointer to whatever type we used on creation
// note: m_iocp is a small wrapper over 'CreateIoCompletionPort' et al.
// getStatus wraps GetQueuedCompletionStatus
m_iocp.getStatus((PDWORD_PTR)&iocp_socket, &dwIoSize, (OVERLAPPED**)&overlapped);
// todo: sth with "extended overlapped struct"
if (dwIoSize)
{
iNetCallback* handler = iocp_socket->m_pHandler;
char buf[1024] = {0};
ULONG ulFlags = 0; //MSG_PARTIAL;
DWORD dwSize = 0;
WSABUF wsabuf = { dwIoSize, (char*)buf };
U32 nRetVal = WSARecv(iocp_socket->m_Socket, &wsabuf, 1, &dwSize, &ulFlags, &overlapped, NULL); //&iocpOverlappedCompletion);
// if an error occurred and it was not an IO PENDING error, output it
if(nRetVal == SOCKET_ERROR)
{
int errCode = WSAGetLastError();
if(errCode != WSA_IO_PENDING)
{
switch(errCode)
{
// handle error
//handler->cb_on_error ( "errorstring" );
}
}
}
if (dwSize)
{ // callback into my application with the received data
handler->cb_received_Data (0,ulFlags,1,0, buf, dwSize);
}
return true;
}
io completion port
Hello, I'm trying to get a working example of io completion ports and I've run into a problem. When the client sends some data to the server, it triggers the first i/o completion event and everything goes well (no errorcode, WSARecv returns correct amount of bytes received and message-data is correct) Now when I receive the next completion event, WSARecv returns WSA_IO_PENDING and lpNumberOfBytesRecvd = 0 and from now on, each thread iteration never returns anything else. Actually I don't quite understand how GetQueuedCompletionStatus works... I pass an 'overlapped' struct into it and there are two situations: - I do a WSARecv which returns 0 (immediately handled) and everything works. Now on the next thread iteration can I re-use the 'overlapped' structure I used (which is should now not be in use anymore)? - I do a WSARecv and it it says 'pending'... what should I do now? Store the overlapped structure in some stl-container? So I'll end up with a vector of overlapped structures which are pending, together with a TCPIocpThread waiting for the next iocp event. Where do I loop over the vector to see if any pending event is ready? Should there be an additional thread doing that? Doesn't that defeat defeat the idea of getting a 'callback' when it is ready?) Currently I'm (re)using the same overlapped structure on each iocp-thread iteration... I assume this is wrong (In case of WSARecv returning 'pending')?
visit my website at www.kalmiya.com
I had a hard time understanding your description of what you're doing, but I hope the following might help:
In IOCP programming, each outstanding request (read, write, etc) needs one OVERLAPPED structure, that stays the same until that particular request has been completed (successfully or with error), or has been cancelled. It is often useful to put the OVERLAPPED structure inside some larger structure (like a class) which contains management data your application might need for the request. If the OVERLAPPED is the first member of the class, you can recover the actual class pointer using a simple cast.
Once you have started an overlapped read request, you don't need to start any more read requests until that has finished, and you don't need to poll the OVERLAPPED status. The whole point of the I/O completion port is that the completion thread will be woken up to service the event, once the request completes.
In IOCP programming, each outstanding request (read, write, etc) needs one OVERLAPPED structure, that stays the same until that particular request has been completed (successfully or with error), or has been cancelled. It is often useful to put the OVERLAPPED structure inside some larger structure (like a class) which contains management data your application might need for the request. If the OVERLAPPED is the first member of the class, you can recover the actual class pointer using a simple cast.
Once you have started an overlapped read request, you don't need to start any more read requests until that has finished, and you don't need to poll the OVERLAPPED status. The whole point of the I/O completion port is that the completion thread will be woken up to service the event, once the request completes.
enum Bool { True, False, FileNotFound };
>I had a hard time understanding your description of what you're doing
It's quite difficult to explain, and it's pretty difficult to grasp
how it's supposed to work so I might be trying to do something stupid...
Let me try to explain better.
I have several threads which are waiting in GetQueuedCompletionStatus.
The client sends a message and one of the threads wakes up.
The thread will now do a WSARecv (that would be the 'outstanding
read request' you mentioned in your reply?)
Now either this read request is finished immediately (when WSARecv
returns 0) or it's 'pending'.
If it's pending, the thread will wait again in GetQueuedCompletionStatus.
Now I don't grasp what I have to do with the pending request...
When the pending request finishes, will it wake up one of the threads
which are waiting in GetQueuedCompletionStatus ?
or where do I get the 'callback' from the system that the overlapped
io is ready and I can query the results?
It's quite difficult to explain, and it's pretty difficult to grasp
how it's supposed to work so I might be trying to do something stupid...
Let me try to explain better.
I have several threads which are waiting in GetQueuedCompletionStatus.
The client sends a message and one of the threads wakes up.
The thread will now do a WSARecv (that would be the 'outstanding
read request' you mentioned in your reply?)
Now either this read request is finished immediately (when WSARecv
returns 0) or it's 'pending'.
If it's pending, the thread will wait again in GetQueuedCompletionStatus.
Now I don't grasp what I have to do with the pending request...
When the pending request finishes, will it wake up one of the threads
which are waiting in GetQueuedCompletionStatus ?
or where do I get the 'callback' from the system that the overlapped
io is ready and I can query the results?
visit my website at www.kalmiya.com
Quote:
When the pending request finishes, will it wake up one of the threads
which are waiting in GetQueuedCompletionStatus ?
Yes. Additionally, it is also important that the OVERLAPPED structure for the request remain un-touched and valid until such time as the request completes.
enum Bool { True, False, FileNotFound };
Yay, I got a first basic version of i/o completion ports working,
with one client connected to a server.
I'm sure I'll be back with more advanced questions :)
...and thanks again for the help!
rating++
with one client connected to a server.
I'm sure I'll be back with more advanced questions :)
...and thanks again for the help!
rating++
visit my website at www.kalmiya.com
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement
Recommended Tutorials
Advertisement