Sign in to follow this  

IOCP - How much this is wrong

This topic is 3313 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I am messing around with iocp for a while, and, in order to achieve my goal(a way to know which of my buffers posted the completion packet) I did something I think is wrong, but I don't know how much is it wrong. Here is the deal: I have a completion key, a class named CClient. In order to send or receive something, this class borrows from the server a CIocpBuffer Object. This CIocpBuffer class holds the OVERLAPPED structure, WSABUF and everything else but the SOCKET, which is within the CClient.When the i/o operation finishes, The server regain this CIocpObjet to be reutilized. CClient can have lot's and lot's of io pending, one WSARecv, and N WSASends at any given time. CClient don't holds any info about what buffers it used to send or recv anything, needer do the CIocpBuffer holds any info about what CClient borrow it. When a completion packet arrived, I had the CClient( completion key), the OVERLAPPED structure, but can't find a way to discover which CIocpBuffer triggered it. So I had this crazy idea!I put a pointer in the OVERLAPPED structure pointing to the buffer used to do the OVERLLAPED I/O call (WSARecv...). The pointer is casted to ULONG_PTR and stored in OVERLAPPED::InternalHigh. Here is some code to help visualization:
// CIocpBuffer constructor
CIocpBuffer::CIocpBuffer(int lenght):ovlp(NULL),cp_buffer(NULL)
{
    buffer_lenght=lenght;
    free=true;
    ovlp=new OVERLAPPED;
    buffer=new WSABUF;
    cp_buffer=new char[buffer_lenght];
    ZeroMemory(ovlp,sizeof(OVERLAPPED));
    ZeroMemory(cp_buffer,buffer_lenght);
    ovlp->InternalHigh = (ULONG_PTR)this;//Here the obscure thing
    buffer->len=buffer_lenght;
    buffer->buf=cp_buffer;
    op_code=FREE;
}

//Client posting WSARecev

int CClient::PostReceive(CIocpBuffer* buffer)
{
     DWORD bytes;
     DWORD flags;
     OVERLAPPED* overlapped=buffer->GetOverlapped();
     WSABUF* buf=buffer->GetWsaBuf();
     flags=0;
     bytes=0; 
    int rcv=WSARecv(s,buf,1,&bytes,&flags,overlapped,NULL);//s=SOCKET
    int error=WSAGetLastError();

  return  rcv;
}


//worker thread
...
BOOL val=GetQueuedCompletionStatus(server->GetIocp(),&bytes,(LPDWORD)&lp_context,&overlapped,INFINITE);
        CClient* client=reinterpret_cast <CClient*>(lp_context);
        if (lp_context==NULL)
        {

            break;//close
        }
        CIocpBuffer* buffer=(CIocpBuffer*)overlapped->InternalHigh;//Casting back
...

MsDN say this about InternalHigh:
Quote:
InternalHigh Reserved. Used internally by the entity that implements overlapped I/O. For service providers that create sockets as IFS handles, this parameter is used by the underlying operating system. NonIFS providers are free to use this parameter as necessary.
NonIFS providers are free to use this parameter as necessary!!! this is working now. So, what do you think? Is it ok? Or is it something very ugly and error prone?

Share this post


Link to post
Share on other sites
That's not OK. However, you should note that the pointer to the OVERLAPPED structure is just that -- a pointer. You can store your back pointer right after the OVERLAPPED, and use casting to recover it. For example:

struct MyOverlapped {
OVERLAPPED ovl;
MyBaseClass * ptr;
};

class MyBaseClass {
stuff
MyOverlapped mol;
more stuff;
};

MyBaseClass mbc;
mbc.mol.ptr = &mbc;

... ReadFile ... &mbc.mol ...

... OnComplete ... LPOVERLAPPED pOverlapped ...
MyBaseClass *pBase = ((MyOverlapped *)pOverlapped)->ptr;
pBase->whatever();

Share this post


Link to post
Share on other sites
Uhh... I See, very cleaver.

And if I inherit from OVERLAPPED, that would work to, right? I would pass my inherited overlapped casted down to OVERLAPPED then I would cast it up back again to my inherited class.

Share this post


Link to post
Share on other sites
Quote:
Original post by Escarab
And if I inherit from OVERLAPPED, that would work to, right? I would pass my inherited overlapped casted down to OVERLAPPED then I would cast it up back again to my inherited class.


Yes, that works as well.

Share this post


Link to post
Share on other sites

This topic is 3313 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this