views:

200

answers:

2

Win32 ReadFileEx is defined as:

BOOL WINAPI ReadFileEx(
  __in       HANDLE hFile,
  __out_opt  LPVOID lpBuffer,
  __in       DWORD nNumberOfBytesToRead,
  __inout    LPOVERLAPPED lpOverlapped,
  __in_opt   LPOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine
);

I am trying to figure out how to make the completion routine (the last argument) invoke a dynamic function pointer when the operation completes. There doesn't seem to be a way to pass in user-data. Any ideas?

A: 

You could use Thread Local Storage... Just create a slot and store a pointer to whatever data you want. Since lpCompletionRoutine runs on the calling thread, you should be fine.

jeffamaphone
+2  A: 

The lpOverlapped function passed into ReadFileEx is passed into the lpCompletionRoutine function.

You can embed the lpOverlapped in your own structure and then use that to find the pointer to your context:

struct ReadFileExContext
{ 
    OVERLAPPED _Overlapped; 
    LPVOID MyContext; 
};

Then in your callback function you cast the LPOVERLAPPED to a ReadFileContext and you're good to go.

Larry Osterman
So... hackish... must... resist... Assuming there is no better way of doing this, your approach actually seems simpler than using TLS (which is yet another mess in C++). Thank you :)
Gili
You're right, it IS hackish. But it does work :).The fundamental problem is that there's not a lot of opportunity for context in the Win32 file I/O family of APIs.
Larry Osterman
At least it's a relatively safe hack, and *way* safer than TLS.
Paul Betts
I just found a great article discussing this approach: http://int64.org/2009/05/14/io-completion-ports-made-easy
Gili