Page 1 of 1

Microsoft : Working With Overlapped I/O Using unblocked reads and writes Rate Topic: -----

#1 Martyn.Rae  Icon User is offline

  • The programming dinosaur
  • member icon

Reputation: 540
  • View blog
  • Posts: 1,406
  • Joined: 22-August 09

Posted 02 April 2010 - 02:12 AM

Microsoft : Working With Overlapped I/O

Introduction

There are times when data can be read from or written to disc and similar devices, and the application does not need to wait for the read or write to complete. The ReadFile and WriteFile functions both block until the input or output has completed. If you look carefully at the documentation though, you will notice that the last parameter described as __inout_opt LPOVERLAPPED lpOverlapped (for normal blocked I/O, this parameter is set to NULL) is the way to achieve this.

Creating or opening a file for overlapped I/O

You have to let the operating system know that the file being opened is subject to overlapped I/O and this is achieved by setting the FILE_FLAG_OVERLAPPED flag in the sixth parameter of the CreateFile function.

    HANDLE file_handle = CreateFile("abc.def", GENERIC_READ|GENERIC_WRITE,
                                    0, NULL, OPEN_EXISTING, 
                                    FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, NULL);



The example above opens a disc file for reading and writing using overlapped I/O.

Issuing overlapped reads and writes to a file

Reads and writes use an OVERLAPPED structure. You need to specify the offset address from the beginning of the file before you use the structure in a read or write operation. The following example shows how to set up the structure correctly.

    OVERLAPPED overlapped_structure;
    memset(&overlapped_structure, 0, sizeof(overlapped_structure));
    overlapped_structure.Offset = 4096;
    overlapped_structure.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);



Once the overlapped structure has been completed, it can be used in an I/O operation such as the example provided below.

    DWORD error_cc = WriteFile(file_handle, buffer, buffer_length, NULL, &overlapped_structure);
    if ( error_cc == FALSE && GetLastError() != ERROR_IO_PENDING ) ...
    ...



Checking for I/O completion

To check if an I/O operation has completed you use the GetOverlappedResult function. This function can be used to periodically check to see if an overlapped I/O operation has completed, or block until the I/O operation has completed by setting the last parameter to FALSE or TRUE respectively.

Pitfalls

There are several pitfalls that can be encountered when using overlapped I/O. One of the most common is forgetting to specify the FILE_FLAG_OVERLAPPED flag when the file is being opened. Another is trying to use the same overlapped structure for a number of simultaneous I/O operations. So, the code below is not correct and could potentially cause all kinds of problems.

    for ( ix = 0; ix < buffer_count; ix++ ) {
        DWORD error_cc = WriteFile(file_handle, buffer[ix],
                                   buffer_length[ix], NULL, 
                                   &overlapped_structure);
        if ( error_cc == FALSE && GetLastError() != ERROR_IO_PENDING ) ...
    }



The correct solution for this would be to have an array of overlapped structures as exampled below.

    for ( ix = 0; ix < buffer_count; ix++ ) {
        DWORD error_cc = WriteFile(file_handle, buffer[ix],
                                   buffer_length, NULL, 
                                   &overlapped_structure[ix]);
        if ( error_cc == FALSE && GetLastError() != ERROR_IO_PENDING ) ...
    }



Conclusion

The ability to read and write data using overlapped I/O is potentially very powerful, especially in server type applications. Overlapped read operations are perhaps less common that overlapped write operations due to the fact that once you have started writing data to a file, it's completion does not have to be checked immediately, but can be performed at some convenient point in time.

Is This A Good Question/Topic? 1
  • +

Page 1 of 1