Click here to Skip to main content
13,349,539 members (53,737 online)
Click here to Skip to main content
Add your own
alternative version


37 bookmarked
Posted 20 Aug 2004

A class to encapsulate the basics of overlapped I/O

, 1 Sep 2004
Rate this:
Please Sign up or sign in to vote.
Overlapped I/O - practice
<!-- Add the rest of your HTML here -->


My very first article on CodeProject discussed one good reason why you might want to use overlapped I/O[^ ]. In that article I used pseudocode to outline the steps needed to use overlapped I/O in order to demonstrate just why you might choose to use it. This time around I'm going to present a usable class that encapsulates the basics of overlapped I/O. What follows assumes that you've read my earlier article.


looks like this. <PRE lang=c++>class COverlappedIO { public: COverlappedIO(void); virtual ~COverlappedIO(void); void Attach(HANDLE hIO); OVERLAPPED *operator&() { return &m_op; } virtual bool Read(BYTE *pbData, DWORD dwBufferSize, LPDWORD pdwBytesRead, HANDLE hStopEvent = INVALID_HANDLE_VALUE); virtual bool Write(BYTE *pbData, DWORD dwBufferSize, HANDLE hStopEvent = INVALID_HANDLE_VALUE); virtual bool Wait(LPDWORD pdwBytesTransferred, HANDLE hStopEvent = INVALID_HANDLE_VALUE); private: HANDLE m_hIO; OVERLAPPED m_op; };

The class uses the create/attach idiom. You create an instance of COverlappedIO , either as a class member, a local variable or on the heap and then attach an open handle to an object you can write to or read from. This can be a file handle, a handle to a named or anonymous pipe, a handle to a comms port or handle to a maislot.

Once you've done the Attach() you Read() or Write() through the object as appropriate. The Write() method takes a pointer to the buffer to be written and the length, in bytes, of the buffer. The Read() method takes the same parameters plus a pointer to a DWORD variable which receives the number of bytes actually read. Both methods also take an optional HANDLE to an event object. If the handle isn't specified in the call it defaults to INVALID_HANDLE_VALUE. If you use the default value the Read() or Write() methods return immediately, having initiated an overlapped I/O operation. If you pass a handle the methods wait until the I/O operation completes or until the handle is signalled. Note that neither method can actually verify that what you passed is a valid event handle; all they can check is if the handle you passed was the default handle of INVALID_HANDLE_VALUE.

The class also doesn't know if the operation you're about to perform on the handle you attached is a valid operation for that handle. If you want to read from the handle you need to ensure the handle was opened with read permissions; likewise for writing. This lack of knowing isn't due to carelessness; there are no API's that I know of that you can call to determine if a handle supports the operation you're about to perform on it, so the class has no choice but to trust you.


looks like this. Write() is similar.

<PRE lang=c++>bool COverlappedIO::Read(BYTE *pbData, DWORD dwBufferSize, LPDWORD pdwBytesRead, HANDLE hStopEvent) { assert(pbData); assert(dwBufferSize); assert(pdwBytesRead); if (m_hIO != INVALID_HANDLE_VALUE) { ::ReadFile(m_hIO, pbData, dwBufferSize, pdwBytesRead, &m_op); if (hStopEvent != INVALID_HANDLE_VALUE) return Wait(pdwBytesRead, hStopEvent); else return true; } // Something went wrong return false; }

We do a bunch of assert s on the parameters and proceed. We check if Attach() has been called to attach a valid handle. If so we initiate a ReadFile() call using overlapped I/O and, if that succeeds, we either return the result of a call to Wait() or true. Which we return depends on whether a valid stop handle was passed.

If you called Read() or Write() without specifying a valid stop handle the call returns after setting up the I/O operation but possibly before it completed. This is normal for overlapped I/O (it's called overlapped for a reason). You initiate an I/O operation and then continue with your normal work. Some time later you need to know if the I/O has completed so that you know it's safe to continue processing. That's where the Wait() method comes in. As with the Read() and Write() methods the Wait() method takes an optional stop event handle. The Wait() method looks like this.

<PRE lang=c++>bool COverlappedIO::Wait(LPDWORD pdwBytesTransferred, HANDLE hStopEvent) { HANDLE hOverlapped[2] = { m_op.hEvent, hStopEvent }; if (m_hIO != INVALID_HANDLE_VALUE) { switch (WaitForMultipleObjects( hStopEvent == INVALID_HANDLE_VALUE ? 1 : 2, hOverlapped, FALSE, INFINITE)) { case WAIT_OBJECT_0: // Signalled on the overlapped event handle, check the result if (GetOverlappedResult(m_hIO, &m_op, pdwBytesTransferred, FALSE)) return true; case WAIT_OBJECT_0 + 1: // Signalled to stop, just stop... return false; } } return false; }

Nothing terribly earth-shattering there. We create a 2 member array containing the overlapped event handle (the one that gets signalled when the overlapped I/O operation completes) and the stop handle. Then we check if the object has actually had an I/O handle attached and if so we fall into a call to WaitForMultipleObjects(), passing it the 2 member array we created earlier and a handle count telling it how many handles to actually monitor. If the stop handle we passed is the default (INVALID_HANDLE_VALUE) then we pass a count of 1 to WaitForMultipleOjects() otherwise we pass a count of 2. Either way, WaitForMultipleObjects() will wait until something happens. If the something is that the overlapped event handle was signalled we then call GetOverlappedResult() to determine if the I/O operation succeeded and return an appropriate status. If anything else happens we return false.


The class cleans up after itself for any objects it created. It won't (and shouldn't) call CloseHandle() on the handle you attached to it. That's the reason there's an Attach() method but there isn't a Detach() method.


August 21, 2004 - Initial version.

September 3, 2004 - Minor changes to the class interface.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Rob Manderson
United States United States
I've been programming for 35 years - started in machine language on the National Semiconductor SC/MP chip, moved via the 8080 to the Z80 - graduated through HP Rocky Mountain Basic and HPL - then to C and C++ and now C#.

I used (30 or so years ago when I worked for Hewlett Packard) to repair HP Oscilloscopes and Spectrum Analysers - for a while there I was the one repairing DC to daylight SpecAns in the Asia Pacific area.

Afterward I was the fourth team member added to the Australia Post EPOS project at Unisys Australia. We grew to become an A$400 million project. I wrote a few device drivers for the project under Microsoft OS/2 v 1.3 - did hardware qualification and was part of the rollout team dealing directly with the customer.

Born and bred in Melbourne Australia, now living in Scottsdale Arizona USA, became a US Citizen on September 29th, 2006.

I work for a medical insurance broker, learning how to create ASP.NET websites in VB.Net and C#. It's all good.

Oh, I'm also a Kentucky Colonel.

You may also be interested in...

Comments and Discussions

GeneralA little confusion Pin
axio18-Jul-05 15:27
memberaxio18-Jul-05 15:27 
GeneralKentucky Colonel Pin
Anonymous2-Jun-05 13:54
sussAnonymous2-Jun-05 13:54 
GeneralRe: Kentucky Colonel Pin
Rob Manderson2-Jun-05 14:05
protectorRob Manderson2-Jun-05 14:05 
GeneralRe: Kentucky Colonel Pin
Anonymous5-Jun-05 14:49
sussAnonymous5-Jun-05 14:49 
QuestionAn example perhaps? Pin
Jerry Evans22-Aug-04 2:53
memberJerry Evans22-Aug-04 2:53 
AnswerRe: An example perhaps? Pin
Rob Manderson4-Oct-04 0:28
protectorRob Manderson4-Oct-04 0:28 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web01 | 2.8.180111.1 | Last Updated 2 Sep 2004
Article Copyright 2004 by Rob Manderson
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid