Рассмотрим простейший пример, в котором необходимо подсчитать количество пробелов в текстовых файлах, имена которых должны указываться в командной строке.
Поскольку нас интересует работа с параллельными задачами, пусть при выполнении программы для каждого из перечисленных в командной строке файлов создается свой процесс (или поток выполнения), который параллельно с другими процессами (потоками) производит работу по подсчету пробелов в «своем» файле. Результатом работы программы будет являться список файлов с подсчитанным количеством пробелов для каждого.
Приведенная ниже реализация программы решения данной задачи не является единственно возможной. В данном случае рассматривается наиболее характерный вариант.
Основная программа запускает потоки и ждет окончания их выполнения. Мы имеем всего один вычислительный процесс, но используем мультизадачные возможности операционной системы Windows.
Листинг 14.1. Подсчет количества пробелов в текстовых файлах
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
//Название: processFile
//Описание: исполняемый код потока
//Входные параметры: lpFileName – имя файла
//Выходные параметры: нет
DWORD processFile(LPVOID lpFileName) {
HANDLE handle; //дескриптор файла
DWORD numRead, total = 0;
char buf;
//Запрос к ОС на открытие файла (только для чтения)
handle = CreateFile((LPCTSTR)lpFileName, GENERIC_READ,
FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
//Цикл чтения до конца файла
do {
//Чтение одного символа из файла
ReadFile(handle,(LPVOID) &buf, 1, &numRead, NULL);
if (buf == 0x20) total++;
} while (numRead>0);
fprintf(stderr,»( ThreadId: %Lu), File %s, spaces = %d\n»,
GetCurrentThreadId(), lpFileName, total);
//Закрытие файла
CloseHandle( handle );
return(0);
}
//Название: main
//Описание: главная программа
//Входные параметры: список имен файлов для обработки
//Выходные параметры: нет
int main( int argc, char *argv[]) {
int i;
DWORD pid;
HANDLE hThrd[255]; //массив ссылок на потоки
//для всех файлов, перечисленных в командной строке
for (i=0; i<(argc-1); i++) {
//запуск потока – обработка одного файла
hThrd[i]=CreateThread( NULL, 0x4000,
(LPTHREAD_START_ROUTINE) processFile,
(LPVOID) argv[i+1], 0, &pid);
fprintf( stdout, «processFile started (HND=%d)\n», hThrd[i]);
}
//ожидание окончания выполнения всех запущенных потоков
WaitForMultipleObjects( argc-1, hThrd, true, INFINITE);
return(0);
}