Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Функция CreateFiber создает новое волокно для потока. Создаваемый поток должен указать начальный адрес кода, который будет выполнять новое волокно. Как правило, начальный адрес — это имя предоставленной пользователем функции. Несколько волокон могут выполнять одну и ту же функцию.
В следующем примере показано, как создавать, планировать и удалять волокна. Волокна выполняют локально определенные функции ReadFiberFunc и WriteFiberFunc. В этом примере реализуется операция копирования файлов на основе волокон. При выполнении примера необходимо указать исходный и конечный файлы. Обратите внимание, что существует множество других способов копирования файлов программными средствами. Этот пример в первую очередь служит для демонстрации использования функций волокон.
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
VOID
__stdcall
ReadFiberFunc(LPVOID lpParameter);
VOID
__stdcall
WriteFiberFunc(LPVOID lpParameter);
void DisplayFiberInfo(void);
typedef struct
{
DWORD dwParameter; // DWORD parameter to fiber (unused)
DWORD dwFiberResultCode; // GetLastError() result code
HANDLE hFile; // handle to operate on
DWORD dwBytesProcessed; // number of bytes processed
} FIBERDATASTRUCT, *PFIBERDATASTRUCT, *LPFIBERDATASTRUCT;
#define RTN_OK 0
#define RTN_USAGE 1
#define RTN_ERROR 13
#define BUFFER_SIZE 32768 // read/write buffer size
#define FIBER_COUNT 3 // max fibers (including primary)
#define PRIMARY_FIBER 0 // array index to primary fiber
#define READ_FIBER 1 // array index to read fiber
#define WRITE_FIBER 2 // array index to write fiber
LPVOID g_lpFiber[FIBER_COUNT];
LPBYTE g_lpBuffer;
DWORD g_dwBytesRead;
int __cdecl _tmain(int argc, TCHAR *argv[])
{
LPFIBERDATASTRUCT fs;
if (argc != 3)
{
printf("Usage: %s <SourceFile> <DestinationFile>\n", argv[0]);
return RTN_USAGE;
}
//
// Allocate storage for our fiber data structures
//
fs = (LPFIBERDATASTRUCT) HeapAlloc(
GetProcessHeap(), 0,
sizeof(FIBERDATASTRUCT) * FIBER_COUNT);
if (fs == NULL)
{
printf("HeapAlloc error (%d)\n", GetLastError());
return RTN_ERROR;
}
//
// Allocate storage for the read/write buffer
//
g_lpBuffer = (LPBYTE)HeapAlloc(GetProcessHeap(), 0, BUFFER_SIZE);
if (g_lpBuffer == NULL)
{
printf("HeapAlloc error (%d)\n", GetLastError());
return RTN_ERROR;
}
//
// Open the source file
//
fs[READ_FIBER].hFile = CreateFile(
argv[1],
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL
);
if (fs[READ_FIBER].hFile == INVALID_HANDLE_VALUE)
{
printf("CreateFile error (%d)\n", GetLastError());
return RTN_ERROR;
}
//
// Open the destination file
//
fs[WRITE_FIBER].hFile = CreateFile(
argv[2],
GENERIC_WRITE,
0,
NULL,
CREATE_NEW,
FILE_FLAG_SEQUENTIAL_SCAN,
NULL
);
if (fs[WRITE_FIBER].hFile == INVALID_HANDLE_VALUE)
{
printf("CreateFile error (%d)\n", GetLastError());
return RTN_ERROR;
}
//
// Convert thread to a fiber, to allow scheduling other fibers
//
g_lpFiber[PRIMARY_FIBER]=ConvertThreadToFiber(&fs[PRIMARY_FIBER]);
if (g_lpFiber[PRIMARY_FIBER] == NULL)
{
printf("ConvertThreadToFiber error (%d)\n", GetLastError());
return RTN_ERROR;
}
//
// Initialize the primary fiber data structure. We don't use
// the primary fiber data structure for anything in this sample.
//
fs[PRIMARY_FIBER].dwParameter = 0;
fs[PRIMARY_FIBER].dwFiberResultCode = 0;
fs[PRIMARY_FIBER].hFile = INVALID_HANDLE_VALUE;
//
// Create the Read fiber
//
g_lpFiber[READ_FIBER]=CreateFiber(0,ReadFiberFunc,&fs[READ_FIBER]);
if (g_lpFiber[READ_FIBER] == NULL)
{
printf("CreateFiber error (%d)\n", GetLastError());
return RTN_ERROR;
}
fs[READ_FIBER].dwParameter = 0x12345678;
//
// Create the Write fiber
//
g_lpFiber[WRITE_FIBER]=CreateFiber(0,WriteFiberFunc,&fs[WRITE_FIBER]);
if (g_lpFiber[WRITE_FIBER] == NULL)
{
printf("CreateFiber error (%d)\n", GetLastError());
return RTN_ERROR;
}
fs[WRITE_FIBER].dwParameter = 0x54545454;
//
// Switch to the read fiber
//
SwitchToFiber(g_lpFiber[READ_FIBER]);
//
// We have been scheduled again. Display results from the
// read/write fibers
//
printf("ReadFiber: result code is %lu, %lu bytes processed\n",
fs[READ_FIBER].dwFiberResultCode, fs[READ_FIBER].dwBytesProcessed);
printf("WriteFiber: result code is %lu, %lu bytes processed\n",
fs[WRITE_FIBER].dwFiberResultCode, fs[WRITE_FIBER].dwBytesProcessed);
//
// Delete the fibers
//
DeleteFiber(g_lpFiber[READ_FIBER]);
DeleteFiber(g_lpFiber[WRITE_FIBER]);
//
// Close handles
//
CloseHandle(fs[READ_FIBER].hFile);
CloseHandle(fs[WRITE_FIBER].hFile);
//
// Free allocated memory
//
HeapFree(GetProcessHeap(), 0, g_lpBuffer);
HeapFree(GetProcessHeap(), 0, fs);
return RTN_OK;
}
VOID
__stdcall
ReadFiberFunc(
LPVOID lpParameter
)
{
LPFIBERDATASTRUCT fds = (LPFIBERDATASTRUCT)lpParameter;
//
// If this fiber was passed NULL for fiber data, just return,
// causing the current thread to exit
//
if (fds == NULL)
{
printf("Passed NULL fiber data; exiting current thread.\n");
return;
}
//
// Display some information pertaining to the current fiber
//
DisplayFiberInfo();
fds->dwBytesProcessed = 0;
while (1)
{
//
// Read data from file specified in the READ_FIBER structure
//
if (!ReadFile(fds->hFile, g_lpBuffer, BUFFER_SIZE,
&g_dwBytesRead, NULL))
{
break;
}
//
// if we reached EOF, break
//
if (g_dwBytesRead == 0) break;
//
// Update number of bytes processed in the fiber data structure
//
fds->dwBytesProcessed += g_dwBytesRead;
//
// Switch to the write fiber
//
SwitchToFiber(g_lpFiber[WRITE_FIBER]);
} // while
//
// Update the fiber result code
//
fds->dwFiberResultCode = GetLastError();
//
// Switch back to the primary fiber
//
SwitchToFiber(g_lpFiber[PRIMARY_FIBER]);
}
VOID
__stdcall
WriteFiberFunc(
LPVOID lpParameter
)
{
LPFIBERDATASTRUCT fds = (LPFIBERDATASTRUCT)lpParameter;
DWORD dwBytesWritten;
//
// If this fiber was passed NULL for fiber data, just return,
// causing the current thread to exit
//
if (fds == NULL)
{
printf("Passed NULL fiber data; exiting current thread.\n");
return;
}
//
// Display some information pertaining to the current fiber
//
DisplayFiberInfo();
//
// Assume all writes succeeded. If a write fails, the fiber
// result code will be updated to reflect the reason for failure
//
fds->dwBytesProcessed = 0;
fds->dwFiberResultCode = ERROR_SUCCESS;
while (1)
{
//
// Write data to the file specified in the WRITE_FIBER structure
//
if (!WriteFile(fds->hFile, g_lpBuffer, g_dwBytesRead,
&dwBytesWritten, NULL))
{
//
// If an error occurred writing, break
//
break;
}
//
// Update number of bytes processed in the fiber data structure
//
fds->dwBytesProcessed += dwBytesWritten;
//
// Switch back to the read fiber
//
SwitchToFiber(g_lpFiber[READ_FIBER]);
} // while
//
// If an error occurred, update the fiber result code...
//
fds->dwFiberResultCode = GetLastError();
//
// ...and switch to the primary fiber
//
SwitchToFiber(g_lpFiber[PRIMARY_FIBER]);
}
void
DisplayFiberInfo(
void
)
{
LPFIBERDATASTRUCT fds = (LPFIBERDATASTRUCT)GetFiberData();
LPVOID lpCurrentFiber = GetCurrentFiber();
//
// Determine which fiber is executing, based on the fiber address
//
if (lpCurrentFiber == g_lpFiber[READ_FIBER])
printf("Read fiber entered");
else
{
if (lpCurrentFiber == g_lpFiber[WRITE_FIBER])
printf("Write fiber entered");
else
{
if (lpCurrentFiber == g_lpFiber[PRIMARY_FIBER])
printf("Primary fiber entered");
else
printf("Unknown fiber entered");
}
}
//
// Display dwParameter from the current fiber data structure
//
printf(" (dwParameter is 0x%lx)\n", fds->dwParameter);
}
В этом примере используется структура данных волокон, которая используется для определения поведения и состояния волокна. Для каждого волокна существует одна структура данных; Указатель на структуру данных передается волокну во время создания волокна с помощью параметра функции FibreProc .
Вызывающий поток вызывает функцию ConvertThreadToFiber , которая позволяет планировать волокна вызывающей стороны. Это также позволяет запланировать волокно другим волокном. Затем поток создает два дополнительных волокна: одно выполняет операции чтения для указанного файла, а другое — операции записи для указанного файла.
Основное волокно вызывает функцию SwitchToFiber для планирования операций чтения. После успешного чтения волокно чтения запланирует выполнение операции записи. После успешной записи в волокно записи, волокно записи запланирует чтение волокно. После завершения цикла чтения и записи планируется основное волокно, что приводит к отображению состояния чтения и записи. Если во время операций чтения или записи возникает ошибка, основное волокно запланировано, и в примере отображается состояние операции.
Перед завершением процесса процесс освобождает волокна с помощью функции DeleteFiber , закрывает дескрипторы файлов и освобождает выделенную память.
Связанные темы