Annotation of q_a/samples/event/asyn_io.c, revision 1.1.1.3

1.1.1.3 ! root        1: 
        !             2: /******************************************************************************\
        !             3: *       This is a part of the Microsoft Source Code Samples. 
        !             4: *       Copyright (C) 1993 Microsoft Corporation.
        !             5: *       All rights reserved. 
        !             6: *       This source code is only intended as a supplement to 
        !             7: *       Microsoft Development Tools and/or WinHelp documentation.
        !             8: *       See these sources for detailed information regarding the 
        !             9: *       Microsoft samples programs.
        !            10: \******************************************************************************/
        !            11: 
1.1.1.2   root       12: /****************************************************************************\
                     13: **   MODULE:  IO.C                                                         **
                     14: **                                                                         **
                     15: **                                                                         **
                     16: **   PURPOSE: Demonstrates the basic concepts envolved when using          **
                     17: **            asynchronous IO. In particular the main advantage is your    **
                     18: **            app more correctly thread can go about doing useful work     **
                     19: **            while waiting for IO. The main disadvantage is you must keep **
                     20: **            track of the file pointer.                                   **
                     21: **                                                                         **
                     22: **   INPUT: Both the File to read and File to write to must be entered     **
                     23: **          on via the command line. Note the file to write to must be     **
                     24: **          unique.                                                        **
                     25: **                                                                         **
                     26: **   FUNCTIONS:                                                            **
                     27: **                                                                         **
                     28: **       Do_BackgroundTask()                                               **
                     29: **                                                                         **
                     30: **                                                                         **
                     31: **   COMMENTS: Reads a file asynchronously writes to another synchronously **
                     32: **                                                                         **
                     33: **                                                                         **
                     34: \***************************************************************************/
                     35: 
                     36: 
                     37: 
1.1       root       38: #define STRICT
                     39: #define NOMINMAX
                     40: #include <windows.h>
                     41: 
                     42: #include <stdlib.h>
                     43: #include <stdio.h>
                     44: #include <memory.h>
                     45: #include <string.h>
                     46: 
                     47: #define DEFAULT           0L
                     48: #define SUCCESS           0L
                     49: #define IO_ERROR          (HANDLE)0xFFFFFFFF
                     50: #define WAIT_ERROR        0xFFFFFFFF
                     51: #define SECTOR_SIZE       1024
                     52: #define RETURN_IMEDIATELY 0L
                     53: 
                     54: #if !defined(HEVENT)
                     55: typedef HANDLE HEVENT;
                     56: #endif
                     57: 
                     58: #if !defined(HFILEEX)
                     59: typedef HANDLE HFILEEX;
                     60: #endif
                     61: 
                     62: VOID ErrorMsg ( PSZ psz ) ;
                     63: VOID Do_BackgroundTask ( VOID ) ;
                     64: 
                     65: 
                     66: 
                     67: void main ( int argc, char *argv[] )
                     68: 
                     69: {
                     70: 
                     71: 
                     72:    HFILEEX    hInfile,  // Handle to the file to read
                     73:             hOutfile; // Handle to the file to write to
                     74: 
                     75:    HEVENT   hEvent ;  // Handle to the synchronization Event
                     76: 
                     77:    OVERLAPPED
1.1.1.3 ! root       78:             OverLapped ; // The operating system does not automatically
        !            79:                          // track the current file position of a file
        !            80:                          // open for asynchroous I/O. Instead one must
        !            81:                          // manually track this by updating the OVERLAPPED
        !            82:                          // structure. To update this structure one uses
        !            83:                          // the result returned by GetOverLappedResults().
1.1       root       84: 
                     85: 
1.1.1.3 ! root       86:    CHAR     buf[SECTOR_SIZE] ; // Buffer used by either
        !            87:                                // ReadFile() or WriteFile()
1.1       root       88: 
1.1.1.3 ! root       89:    DWORD    cbBytesRead,         // count of bytes read by ReadFile()
        !            90:                                  // When asynchonous I/O is performed
        !            91:                                  // one must check how many bytes were
        !            92:                                  // read by calling GetOverLappedResults().
1.1       root       93: 
                     94: 
1.1.1.3 ! root       95:             cbBytesWritten,      // count of bytes written by WriteFile()
1.1       root       96: 
1.1.1.3 ! root       97:             cbBytesTransfered ;  // this value is returned by
        !            98:                                  // GetOverLappedResults() represents the
        !            99:                                  // count of bytes transfered asynchronous
1.1       root      100: 
1.1.1.3 ! root      101:    DWORD    dwStatus,            // value returned by GetLastError()
1.1       root      102:             dwSuccess ;          // return code of last API called
                    103: 
                    104:    BOOL     bSuccess ;           // return code of last API called
                    105: 
                    106:    CHAR     buffer[80] ;
                    107: 
                    108: /***************************************************************************\
1.1.1.3 ! root      109: **                                                                         **
1.1       root      110: **  This block of code initalizes all the necessary variables needed to do **
                    111: **  asynchronous IO. Specfically it opens the files and initializes the    **
                    112: **  synchronization EVENT and OVERLAPPED structure needed to keep track    **
                    113: **  of asynchronous file I/O                                               **
1.1.1.3 ! root      114: **                                                                         **
1.1       root      115: \***************************************************************************/
                    116: 
                    117: 
                    118:    if ( argc != 3 )
                    119:    {
                    120:       printf ( "\nUsage: IO1 input_file output_file\n" ) ;
                    121:       exit ( EXIT_FAILURE ) ;
                    122:    }
                    123: 
                    124: 
                    125: 
                    126: /*
                    127:  * Open file which we will be copying. Note we are opening this
                    128:  * asynchronously.
                    129:  */
                    130: 
                    131:    hInfile = CreateFile
1.1.1.3 ! root      132:                   (
        !           133:                      argv[1]              // File to read
        !           134:                     ,GENERIC_READ         // Open file for reading only
        !           135:                     ,FILE_SHARE_READ      // Allow others to read file
        !           136:                     ,NULL                 // No security
        !           137:                     ,OPEN_EXISTING        // Fail if file doesn't exit
        !           138:                     ,FILE_FLAG_OVERLAPPED // Async I/o
        !           139:                     ,DEFAULT
        !           140:                   ) ;
1.1       root      141: 
                    142: 
                    143:    if ( hInfile == IO_ERROR )
                    144:    {
                    145:       strcpy ( buffer, "Error opening" ) ;
                    146:       strcat ( buffer, argv[1] ) ;
                    147:       ErrorMsg ( buffer ) ;
                    148:    }
                    149: 
                    150: 
                    151: /*
                    152:  * Create the file to write to; here we have opened it for synchronous IO.
                    153:  */
                    154: 
                    155:    hOutfile = CreateFile
1.1.1.3 ! root      156:                   (
        !           157:                      argv[2]                 // File to write to
        !           158:                     ,GENERIC_WRITE           // Open file only to write to
        !           159:                     ,DEFAULT                 // No sharing allowed
        !           160:                     ,NULL                    // No security
        !           161:                     ,CREATE_NEW              // Fail if file exists
        !           162:                     ,FILE_ATTRIBUTE_NORMAL   // No attributes
        !           163:                     ,DEFAULT
        !           164:                   ) ;
1.1       root      165: 
                    166: 
                    167:    if ( hOutfile == IO_ERROR )
                    168:    {
                    169:       strcpy ( buffer, "Error opening" ) ;
                    170:       strcat ( buffer, argv[1] ) ;
                    171:       ErrorMsg ( buffer ) ;
                    172:    }
                    173: 
                    174: 
                    175: 
                    176: /*
                    177:  * Create Synchronoizing Event
                    178:  */
                    179: 
                    180:    hEvent = CreateEvent
1.1.1.3 ! root      181:                     (
        !           182:                       NULL    // No security
        !           183:                      ,TRUE    // Manual reset
        !           184:                      ,FALSE   // Initially Event set to non-signaled state
        !           185:                      ,NULL    // No name
        !           186:                     ) ;
1.1       root      187:    if ( !hEvent )
                    188:       ErrorMsg ( "Error creating Event" ) ;
                    189: 
                    190: 
                    191: /*
                    192:  * Intialize OverLapped structure. We will be using an Event instead
                    193:  * of the file handle for synchronizing I/O. One reason to use a unique
                    194:  * event instead of the file handle would be a so multi-threaded app
                    195:  * would know which thread to unblock when the handle is set to the
                    196:  * signaled state.
                    197:  */
                    198: 
                    199:    memset ( &OverLapped, 0, sizeof ( OVERLAPPED ) ) ;
                    200:    OverLapped.hEvent = hEvent ;
                    201: 
                    202: 
                    203:    bSuccess = TRUE ;
                    204: 
                    205: 
                    206: /***************************************************************************\
                    207: **                                                                         **
                    208: ** This is the main function of this program. Here we loop until the file  **
                    209: ** has been copied. Notice that even though we are using asynchronous I/O  **
                    210: ** ReadFile() may still return sychronously if it can be done fast enough  **
1.1.1.3 ! root      211: **                                                                         **
1.1       root      212: \***************************************************************************/
                    213: 
                    214:    while ( bSuccess )
                    215:    {
                    216: 
                    217: /*
                    218:  * Read file asynchronously
                    219:  */
                    220: 
                    221:       bSuccess = ReadFile
1.1.1.3 ! root      222:             (
        !           223:                hInfile        // Handle of file to read
        !           224:               ,buf            // Buffer to store input
        !           225:               ,SECTOR_SIZE    // Number of bytes to read
        !           226:               ,&cbBytesRead   // Number of bytes read. See note]
        !           227:                               // above in delcaration
        !           228:               ,&OverLapped    // Used for asynchronous I/O
        !           229:             ) ;
1.1       root      230: 
                    231: 
                    232: 
                    233: /*
                    234:  * Check whether ReadFile() has completed yet
                    235:  */
                    236:       if ( !bSuccess && (( dwStatus = GetLastError ()) == ERROR_IO_PENDING ) )
                    237:       {
1.1.1.3 ! root      238:         printf ( "\nIO Pending" ) ;
1.1       root      239: /*
                    240:  * Read not complete yet first execute the background task then check
                    241:  * to the if event "hEvent" set to the signaled state. If the event is
                    242:  * not set signaled state then loop through again - run the background
                    243:  * task and check the event.
                    244:  *
                    245:  */
                    246: 
                    247:         Do_BackgroundTask () ;
                    248: 
                    249:         dwSuccess = WaitForSingleObject ( hEvent, RETURN_IMEDIATELY ) ;
                    250: 
1.1.1.3 ! root      251:         if ( dwSuccess == WAIT_ERROR )
        !           252:             ErrorMsg("Error in WaitForSingleObject") ;
        !           253:         else if ( dwSuccess == SUCCESS )
1.1       root      254:         {
                    255: 
                    256:             bSuccess = GetOverlappedResult(
                    257:                             hInfile, &OverLapped, &cbBytesTransfered, FALSE) ;
                    258:             if ( !bSuccess )
                    259:                 ErrorMsg ( "Error in GetOverLappedResult" ) ;
                    260:             else
                    261:             {
1.1.1.3 ! root      262:                 // Read has completed now find out how many bytes have been read
1.1       root      263: 
1.1.1.3 ! root      264:                 printf ( "\nNumber of bytes transfered is %d\n", cbBytesTransfered ) ;
        !           265:                 OverLapped.Offset += cbBytesTransfered ;
        !           266:                 cbBytesRead = cbBytesTransfered ;
1.1       root      267:             }
                    268:         }
                    269:         else if ( dwSuccess == WAIT_TIMEOUT )
                    270:             Do_BackgroundTask () ;
                    271:       }
                    272: /*
                    273:  * ReadFile() read file synchronously; update Overlapped structure
                    274:  */
                    275:       else if ( bSuccess  && cbBytesRead != 0 )
                    276:       {
1.1.1.3 ! root      277:          printf ( "\nNumber of bytes transfered is %d\n", cbBytesRead ) ;
        !           278:          OverLapped.Offset += cbBytesRead ;
1.1       root      279:       }
                    280: /*
                    281:  * ReadFile() has found the end of the file; exit loop
                    282:  */
                    283:       else if ( bSuccess  && cbBytesRead == 0 )
                    284:       {
1.1.1.3 ! root      285:          printf ( "End of file read\n" ) ;
        !           286:          break ;
1.1       root      287:       }
                    288: /*
                    289:  * An error occured while reading, print out status and exit loop.
                    290:  */
                    291:       else
1.1.1.3 ! root      292:          ErrorMsg ( "Error reading to file" ) ;
1.1       root      293: 
                    294: 
                    295: 
                    296: /*
                    297:  * Write to file synchronously
                    298:  */
                    299:       bSuccess = WriteFile
1.1.1.3 ! root      300:             (
        !           301:                hOutfile             // Handle of file to write to
        !           302:               ,buf                  // Data to write to file
        !           303:               ,cbBytesRead          // Number of bytes to write
        !           304:               ,&cbBytesWritten      // Number of bytes written
        !           305:               ,NULL                 // Only need for asynchonous output
        !           306:             ) ;
1.1       root      307: 
                    308: 
                    309:       if ( !bSuccess )
1.1.1.3 ! root      310:          ErrorMsg ( "Error writing to file" ) ;
1.1       root      311: 
                    312:    } // End of WHILE loop
                    313: 
                    314: 
                    315: 
1.1.1.3 ! root      316:    CloseHandle ( hInfile ) ;        // Close handle to input file
1.1       root      317:    FlushFileBuffers ( hOutfile ) ;  // Make sure all data written to file first
1.1.1.3 ! root      318:    CloseHandle ( hOutfile ) ;       // Close handle to output file
1.1       root      319:    exit ( EXIT_SUCCESS ) ;
                    320: 
                    321: }
                    322: 
                    323: 
                    324: 
                    325: /***************************************************************************\
                    326: **                                                                         **
                    327: **   FUNCTION: ErrorMsg(LPTSTR)                                            **
                    328: **                                                                         **
                    329: **   PURPOSE: Prints out an error message the return code of the last API  **
                    330: **            to fail.                                                     **
                    331: **                                                                         **
                    332: **   INPUT: psz: This string is a description of where the code failed in  **
                    333: **          the module                                                     **
                    334: **                                                                         **
                    335: **   OUTPUT: None                                                          **
                    336: **                                                                         **
                    337: \****************************************************************************/
                    338: 
                    339: VOID ErrorMsg ( PSZ psz )
                    340: {
                    341: 
                    342:   printf ("\n%s: return code = %d\n", psz, GetLastError()) ;
                    343:   exit ( EXIT_FAILURE ) ;
                    344: }
                    345: 
                    346: /***************************************************************************\
                    347: **                                                                         **
                    348: **   FUNCTION: Do_BackgroundTask ( VOID )                                  **
                    349: **                                                                         **
                    350: **   PURPOSE: Works in the background while IO sytems                      **
                    351: **                                                                         **
                    352: **   COMMENTS:                                                             **
                    353: **                                                                         **
                    354: **      Currently this does nothing if I have the time I will come up      **
                    355: **      with some silly task to keep the user entertained.                 **
                    356: **                                                                         **
                    357: **   INPUT: None                                                           **
                    358: **                                                                         **
                    359: **   OUTPUT: None                                                          **
                    360: **                                                                         **
                    361: \***************************************************************************/
                    362: 
                    363: VOID Do_BackgroundTask ( VOID )
                    364: {
                    365:   Sleep ( 5000L ) ;
                    366: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.