Annotation of q_a/samples/event/asyn_io.c, revision 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.