Synchronization and Overlapped Input and Output
The Win32 API supports both synchronous and asynchronous (or overlapped) I/O operations on files, named pipes, and serial communications devices. The WriteFile, ReadFile, DeviceIoControl, WaitCommEvent, ConnectNamedPipe, and TransactNamedPipe functions can be performed either synchronously or asynchronously. The ReadFileEx and WriteFileEx functions can be performed asynchronously only.
When a function is executed synchronously, it does not return until the operation has been completed. This means that the execution of the calling thread can be blocked for an indefinite period while it waits for a time-consuming operation to finish. Functions called for overlapped operation can return immediately, even though the operation has not been completed. This enables a time-consuming I/O operation to be executed in the background while the calling thread is free to perform other tasks. For example, a single thread can perform simultaneous I/O operations on different handles, or even simultaneous read and write operations on the same handle.
To synchronize its execution with the completion of the overlapped operation, the calling thread uses the GetOverlappedResult function or one of the wait functions to determine when the overlapped operation has been completed. You can also use the HasOverlappedIoCompleted macro to poll for completion.
To cancel all pending asynchronous I/O operations, use the CancelIO function. This function only cancels operations issued by the calling thread for the specified file handle.
Overlapped operations require a file, named pipe, or communications device that was created with the FILE_FLAG_OVERLAPPED flag. To call a function to perform an overlapped operation, the calling thread must specify a pointer to an OVERLAPPED structure. If this pointer is NULL, the function return value may incorrectly indicate that the operation completed. The OVERLAPPED structure must contain a handle to a manual-reset ¾ not an auto-reset ¾ event object. The system sets the state of the event object to nonsignaled when a call to the I/O function returns before the operation has been completed. The system sets the state of the event object to signaled when the operation has been completed.
When a function is called to perform an overlapped operation, it is possible that the operation will be completed before the function returns. When this happens, the results are handled as if the operation had been performed synchronously. If the operation was not completed, however, the function's return value is FALSE, and the GetLastError function returns ERROR_IO_PENDING.
A thread can manage overlapped operations by either of two methods:
·Use the GetOverlappedResult function to wait for the overlapped operation to be completed.
·Specify a handle to the OVERLAPPED structure's manual-reset event object in one of the wait functions and then call GetOverlappedResult after the wait function returns. The GetOverlappedResult function returns the results of the completed overlapped operation, and for functions in which such information is appropriate, it reports the actual number of bytes that were transferred.
When performing multiple simultaneous overlapped operations, the calling thread must specify an OVERLAPPED structure with a different manual-reset event object for each operation. To wait for any one of the overlapped operations to be completed, the thread specifies all the manual-reset event handles as wait criteria in one of the multiple-object wait functions. The return value of the multiple-object wait function indicates which manual-reset event object was signaled, so the thread can determine which overlapped operation caused the wait operation to be completed.
If no event object is specified in the OVERLAPPED structure, the system signals the state of the file, named pipe, or communications device when the overlapped operation has been completed. Thus, you can specify these handles as synchronization objects in a wait function, though their use for this purpose can be difficult to manage. When performing simultaneous overlapped operations on the same file, named pipe, or communications device, there is no way to know which operation caused the object's state to be signaled. It is safer to use a separate event object for each overlapped operation.
For examples that illustrate the use of overlapped operations, completion routines, and the GetOverlappedResult function, see Using Pipes.