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

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

unix.superglobalmegacorp.com

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