FIBERS.C
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:10k
源码类别:

Windows编程

开发平台:

Visual C++

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