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

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

unix.superglobalmegacorp.com

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