home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / winbase / fibers / fibers.c next >
C/C++ Source or Header  |  1997-10-05  |  10KB  |  390 lines

  1. /*++
  2.  
  3. Copyright (c) 1995-1997  Microsoft Corporation
  4.  
  5. Module Name:
  6.  
  7.     fibers.c
  8.  
  9. Abstract:
  10.  
  11.     This module illustrates the Win32 fiber APIs.
  12.  
  13.     This example implements a fiber based file copy operation.  Note that
  14.     a number of different techiques exists for copying files programmatically;
  15.     this sample simply illustrates the fiber APIs.
  16.  
  17.     This example makes use of a fiber data structure which is used to
  18.     determine the behavior and state of the fiber.  One data structure
  19.     exists for each fiber; the pointer to the data structure is passed
  20.     to the fiber at fiber creation time via the lpParameter fiber parameter.
  21.  
  22.     The executing thread in the process makes a call to ConvertThreadToFiber,
  23.     which allows fibers to be scheduled by the caller.  This also allows
  24.     the resultant fiber to be scheduled by another fiber.
  25.  
  26.     Next, two additional fibers are created, one fiber which performs read
  27.     operations against a specified file, and another fiber which performs
  28.     the write operations against a specified file.
  29.  
  30.     The primary fiber then schedules the read fiber.  After a succesful
  31.     read, the read fiber schedules the write fiber.  After a succesful write
  32.     in the write fiber, the write fiber schedules the read fiber.  When
  33.     the read/write cycle has completed, the primary fiber is scheduled,
  34.     which results in the display of the read/write status. If an error occurs
  35.     during the read or write fibers, the primary fiber is scheduled and status
  36.     of the read/write is displayed.
  37.  
  38.     The fibers, fiber data structures, and file handles are then freed
  39.     prior to process termination.
  40.  
  41. Author:
  42.  
  43.     Scott Field (sfield) 30-Nov-95
  44.  
  45. Revision History:
  46.  
  47. --*/
  48.  
  49. #include <windows.h>
  50. #include <stdio.h>
  51.  
  52. VOID
  53. __stdcall
  54. ReadFiberFunc(
  55.     LPVOID lpParameter
  56.     );
  57.  
  58. VOID
  59. __stdcall
  60. WriteFiberFunc(
  61.     LPVOID lpParameter
  62.     );
  63.  
  64. void
  65. DisplayFiberInfo(
  66.     void
  67.     );
  68.  
  69. typedef struct {
  70.     DWORD dwParameter;          // DWORD parameter to fiber (unused)
  71.     DWORD dwFiberResultCode;    // GetLastError() result code
  72.     HANDLE hFile;               // handle to operate on
  73.     DWORD dwBytesProcessed;     // number of bytes processed
  74. } FIBERDATASTRUCT, *PFIBERDATASTRUCT, *LPFIBERDATASTRUCT;
  75.  
  76. #define RTN_OK 0
  77. #define RTN_USAGE 1
  78. #define RTN_ERROR 13
  79.  
  80. #define BUFFER_SIZE 32768   // read/write buffer size
  81. #define FIBER_COUNT 3       // total number of fibers (including primary)
  82.  
  83. #define PRIMARY_FIBER 0 // array index to primary fiber
  84. #define READ_FIBER 1    // array index to read fiber
  85. #define WRITE_FIBER 2   // array index to write fiber
  86.  
  87. LPVOID g_lpFiber[FIBER_COUNT];
  88. LPBYTE g_lpBuffer;
  89. DWORD g_dwBytesRead;
  90.  
  91. int
  92. __cdecl
  93. main(
  94.     int argc,
  95.     char *argv[]
  96.     )
  97. {
  98.     LPFIBERDATASTRUCT fs;
  99.  
  100.     if(argc != 3) {
  101.         printf("Usage: %s <SourceFile> <DestinationFile>\n", argv[0]);
  102.         return RTN_USAGE;
  103.     }
  104.  
  105.     //
  106.     // allocate storage for our fiber data structures
  107.     //
  108.     fs = (LPFIBERDATASTRUCT)HeapAlloc(
  109.         GetProcessHeap(), 0, sizeof(FIBERDATASTRUCT) * FIBER_COUNT);
  110.  
  111.     if(fs == NULL) {
  112.         printf("HeapAlloc error! (rc%=lu)\n", GetLastError());
  113.         return RTN_ERROR;
  114.     }
  115.  
  116.     //
  117.     // allocate storage for the read/write buffer
  118.     //
  119.     g_lpBuffer = (LPBYTE)HeapAlloc(GetProcessHeap(), 0, BUFFER_SIZE);
  120.     if(g_lpBuffer == NULL) {
  121.         printf("HeapAlloc error! (rc=%lu)\n", GetLastError());
  122.         return RTN_ERROR;
  123.     }
  124.  
  125.     //
  126.     // open the source file
  127.     //
  128.     fs[READ_FIBER].hFile = CreateFile(
  129.         argv[1],
  130.         GENERIC_READ,
  131.         FILE_SHARE_READ,
  132.         NULL,
  133.         OPEN_EXISTING,
  134.         FILE_FLAG_SEQUENTIAL_SCAN,
  135.         NULL
  136.         );
  137.  
  138.     if(fs[READ_FIBER].hFile == INVALID_HANDLE_VALUE) {
  139.         printf("CreateFile error! (rc=%lu)\n", GetLastError());
  140.         return RTN_ERROR;
  141.     }
  142.  
  143.     //
  144.     // open the destination file
  145.     //
  146.     fs[WRITE_FIBER].hFile = CreateFile(
  147.         argv[2],
  148.         GENERIC_WRITE,
  149.         0,
  150.         NULL,
  151.         CREATE_NEW,
  152.         FILE_FLAG_SEQUENTIAL_SCAN,
  153.         NULL
  154.         );
  155.  
  156.     if(fs[WRITE_FIBER].hFile == INVALID_HANDLE_VALUE) {
  157.         printf("CreateFile error! (rc=%lu)\n", GetLastError());
  158.         return RTN_ERROR;
  159.     }
  160.  
  161.     //
  162.     // convert this thread to a fiber, to allow scheduling of other fibers
  163.     //
  164.     g_lpFiber[PRIMARY_FIBER] = ConvertThreadToFiber(&fs[PRIMARY_FIBER]);
  165.  
  166.     if(g_lpFiber[PRIMARY_FIBER] == NULL) {
  167.         printf("ConvertThreadToFiber failed! rc=%lu\n", GetLastError());
  168.         return RTN_ERROR;
  169.     }
  170.  
  171.     //
  172.     // Just initialize the primary fiber data structure.  We don't use
  173.     // the primary fiber data structure for anything in this sample.
  174.     //
  175.     fs[PRIMARY_FIBER].dwParameter = 0;
  176.     fs[PRIMARY_FIBER].dwFiberResultCode = 0;
  177.     fs[PRIMARY_FIBER].hFile = INVALID_HANDLE_VALUE;
  178.  
  179.     //
  180.     // create the Read fiber
  181.     //
  182.     g_lpFiber[READ_FIBER] = CreateFiber(0, ReadFiberFunc, &fs[READ_FIBER]);
  183.  
  184.     if(g_lpFiber[READ_FIBER] == NULL) {
  185.         printf("CreateFiber error! (rc=%lu)\n", GetLastError());
  186.         return RTN_ERROR;
  187.     }
  188.  
  189.     fs[READ_FIBER].dwParameter = 0x12345678;
  190.  
  191.     //
  192.     // create the Write fiber
  193.     //
  194.     g_lpFiber[WRITE_FIBER]=CreateFiber(0, WriteFiberFunc, &fs[WRITE_FIBER]);
  195.  
  196.     if(g_lpFiber[WRITE_FIBER] == NULL) {
  197.         printf("CreateFiber error! (rc=%lu)\n", GetLastError());
  198.         return RTN_ERROR;
  199.     }
  200.  
  201.     fs[WRITE_FIBER].dwParameter = 0x54545454;
  202.  
  203.     //
  204.     // switch to the read fiber
  205.     //
  206.     SwitchToFiber(g_lpFiber[READ_FIBER]);
  207.  
  208.     //
  209.     // We have now been scheduled again.  Display results from the read/write
  210.     // fibers
  211.     //
  212.     printf("ReadFiber result == %lu Bytes Processed == %lu\n",
  213.         fs[READ_FIBER].dwFiberResultCode, fs[READ_FIBER].dwBytesProcessed);
  214.  
  215.     printf("WriteFiber result == %lu Bytes Processed == %lu\n",
  216.         fs[WRITE_FIBER].dwFiberResultCode, fs[WRITE_FIBER].dwBytesProcessed);
  217.  
  218.     //
  219.     // Delete the fibers
  220.     //
  221.     DeleteFiber(g_lpFiber[READ_FIBER]);
  222.     DeleteFiber(g_lpFiber[WRITE_FIBER]);
  223.  
  224.     //
  225.     // close handles
  226.     //
  227.     CloseHandle(fs[READ_FIBER].hFile);
  228.     CloseHandle(fs[WRITE_FIBER].hFile);
  229.  
  230.     //
  231.     // free allocated memory
  232.     //
  233.     HeapFree(GetProcessHeap(), 0, g_lpBuffer);
  234.     HeapFree(GetProcessHeap(), 0, fs);
  235.  
  236.     return RTN_OK;
  237. }
  238.  
  239. VOID
  240. __stdcall
  241. ReadFiberFunc(
  242.     LPVOID lpParameter
  243.     )
  244. {
  245.     LPFIBERDATASTRUCT fds = (LPFIBERDATASTRUCT)lpParameter;
  246.  
  247.     //
  248.     // if this fiber was passed NULL for fiber data, just return,
  249.     // causing the current thread to exit
  250.     //
  251.     if(fds == NULL) {
  252.         printf("Passed NULL fiber data.  Exiting current thread.\n");
  253.         return;
  254.     }
  255.  
  256.     //
  257.     // display some information pertaining to the current fiber
  258.     //
  259.     DisplayFiberInfo();
  260.  
  261.     fds->dwBytesProcessed = 0;
  262.  
  263.     while(1) {
  264.         //
  265.         // read data from file specified in the READ_FIBER data structure
  266.         //
  267.         if(!ReadFile(fds->hFile, g_lpBuffer, BUFFER_SIZE, &g_dwBytesRead, NULL)) {
  268.             break;
  269.         }
  270.  
  271.         //
  272.         // if we reached EOF, break
  273.         //
  274.         if(g_dwBytesRead == 0) break;
  275.  
  276.         //
  277.         // update number of bytes processed in the fiber data structure
  278.         //
  279.         fds->dwBytesProcessed += g_dwBytesRead;
  280.  
  281.         //
  282.         // switch to the write fiber
  283.         //
  284.         SwitchToFiber(g_lpFiber[WRITE_FIBER]);
  285.     } // while
  286.  
  287.     //
  288.     // update the fiber result code
  289.     //
  290.     fds->dwFiberResultCode = GetLastError();
  291.  
  292.     //
  293.     // switch back to the primary fiber
  294.     //
  295.     SwitchToFiber(g_lpFiber[PRIMARY_FIBER]);
  296. }
  297.  
  298. VOID
  299. __stdcall
  300. WriteFiberFunc(
  301.     LPVOID lpParameter
  302.     )
  303. {
  304.     LPFIBERDATASTRUCT fds = (LPFIBERDATASTRUCT)lpParameter;
  305.     DWORD dwBytesWritten;
  306.  
  307.     //
  308.     // if this fiber was passed NULL for fiber data, just return,
  309.     // causing the current thread to exit
  310.     //
  311.     if(fds == NULL) {
  312.         printf("Passed NULL fiber data.  Exiting current thread.\n");
  313.         return;
  314.     }
  315.  
  316.     //
  317.     // display some information pertaining to the current fiber
  318.     //
  319.     DisplayFiberInfo();
  320.  
  321.     //
  322.     // assume all of the writes succeed.  If a write fails, the fiber
  323.     // result code will be updated to reflect the reason for failure
  324.     //
  325.     fds->dwBytesProcessed = 0;
  326.     fds->dwFiberResultCode = ERROR_SUCCESS;
  327.  
  328.     while (1) {
  329.         //
  330.         // write data to the file specified in the WRITE_FIBER data structure
  331.         //
  332.         if(!WriteFile(fds->hFile, g_lpBuffer, g_dwBytesRead, &dwBytesWritten, NULL)) {
  333.             //
  334.             // if an error occurred writing, break
  335.             //
  336.             break;
  337.         }
  338.  
  339.         //
  340.         // update number of bytes processed in the fiber data structure
  341.         //
  342.         fds->dwBytesProcessed += dwBytesWritten;
  343.  
  344.         //
  345.         // switch back to the read fiber
  346.         //
  347.         SwitchToFiber(g_lpFiber[READ_FIBER]);
  348.     }  // while
  349.  
  350.     //
  351.     // if an error occurred, update the fiber result code...
  352.     //
  353.     fds->dwFiberResultCode = GetLastError();
  354.  
  355.     //
  356.     // ...and switch to the primary fiber
  357.     //
  358.     SwitchToFiber(g_lpFiber[PRIMARY_FIBER]);
  359. }
  360.  
  361. void
  362. DisplayFiberInfo(
  363.     void
  364.     )
  365. {
  366.     LPFIBERDATASTRUCT fds = (LPFIBERDATASTRUCT)GetFiberData();
  367.     LPVOID lpCurrentFiber = GetCurrentFiber();
  368.  
  369.     //
  370.     // determine which fiber we are executing, based on the fiber address
  371.     //
  372.     if(lpCurrentFiber == g_lpFiber[READ_FIBER])
  373.         printf("Read Fiber entered");
  374.     else {
  375.         if(lpCurrentFiber == g_lpFiber[WRITE_FIBER])
  376.             printf("Write Fiber entered");
  377.         else {
  378.             if(lpCurrentFiber == g_lpFiber[PRIMARY_FIBER])
  379.                 printf("Primary Fiber entered");
  380.             else
  381.                 printf("Unknown Fiber entered");
  382.             }
  383.     }
  384.  
  385.     //
  386.     // display dwParameter from the current fiber data structure
  387.     //
  388.     printf(" (dwParameter == 0x%lx)\n", fds->dwParameter);
  389. }
  390.