Example: Parallel Pattern Searching
Now is the time to put Windows processes to the test. This example, grepMP, creates processes to search for patterns in files, one process per search file. The pattern search program is modeled after the UNIX grep utility, although the technique would apply to any program that uses standard output. The search program should be regarded as a black box and is simply an executable program to be controlled by a parent process.The command line to the program is of the form
grepMP pattern F1 F2 ... FN
The program, Program 2-3) outputs the temporary file.
Figure 6-3 shows the processing performed by Program 6-1.
Program 6-1. grepMP: Parallel Searching
/* Chapter 6. grepMP. */
/* Multiple process version of grep command. */
#include "EvryThng.h"
int _tmain (DWORD argc, LPTSTR argv [])
/* Create a separate process to search each file on the
command line. Each process is given a temporary file,
in the current directory, to receive the results. */
{
HANDLE hTempFile;
SECURITY_ATTRIBUTES StdOutSA = /* SA for inheritable handle. */
{sizeof (SECURITY_ATTRIBUTES), NULL, TRUE};
TCHAR CommandLine [MAX_PATH + 100];
STARTUPINFO StartUpSearch, StartUp;
PROCESS_INFORMATION ProcessInfo;
DWORD iProc, ExCode;
HANDLE *hProc; /* Pointer to an array of proc handles. */
typedef struct {TCHAR TempFile [MAX_PATH];} PROCFILE;
PROCFILE *ProcFile; /* Pointer to array of temp file names. */
GetStartupInfo (&StartUpSearch);
GetStartupInfo (&StartUp);
ProcFile = malloc ((argc - 2) * sizeof (PROCFILE));
hProc = malloc ((argc - 2) * sizeof (HANDLE));
/* Create a separate "grep" process for each file. */
for (iProc = 0; iProc < argc - 2; iProc++) {
_stprintf (CommandLine, _T ("%s%s %s"),
_T ("grep "), argv [1], argv [iProc + 2]);
GetTempFileName (_T ("."), _T ("gtm"), 0,
ProcFile [iProc].TempFile); /* For search results. */
hTempFile = /* This handle is inheritable */
CreateFile (ProcFile [iProc].TempFile,
GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, &StdOutSA,
CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
StartUpSearch.dwFlags = STARTF_USESTDHANDLES;
StartUpSearch.hStdOutput = hTempFile;
StartUpSearch.hStdError = hTempFile;
StartUpSearch.hStdInput = GetStdHandle (STD_INPUT_HANDLE);
/* Create a process to execute the command line. */
CreateProcess (NULL, CommandLine, NULL, NULL,
TRUE, 0, NULL, NULL, &StartUpSearch, &ProcessInfo);
/* Close unwanted handles. */
CloseHandle (hTempFile); CloseHandle (ProcessInfo.hThread);
hProc [iProc] = ProcessInfo.hProcess;
}
/* Processes are all running. Wait for them to complete. */
for (iProc = 0; iProc < argc - 2; iProc += MAXIMUM_WAIT_OBJECTS)
WaitForMultipleObjects ( /* Allows a large # of processes */
min (MAXIMUM_WAIT_OBJECTS, argc - 2 - iProc),
&hProc [iProc], TRUE, INFINITE);
/* Result files sent to std output using "cat." */
for (iProc = 0; iProc < argc - 2; iProc++) {
if (GetExitCodeProcess(hProc [iProc], &ExCode) && ExCode==0) {
/* Pattern was detected -- List results. */
if (argc > 3) _tprintf (_T ("%s:\n"), argv [iProc + 2]);
fflush (stdout); /* Multiple processes use stdout. */
_stprintf (CommandLine, _T ("%s%s"),
_T ("cat "), ProcFile [iProc].TempFile);
CreateProcess (NULL, CommandLine, NULL, NULL,
TRUE, 0, NULL, NULL, &StartUp, &ProcessInfo);
WaitForSingleObject (ProcessInfo.hProcess, INFINITE);
CloseHandle (ProcessInfo.hProcess);
CloseHandle (ProcessInfo.hThread);
}
CloseHandle (hProc [iProc]);
DeleteFile (ProcFile [iProc].TempFile);
}
free (ProcFile);
free (hProc);
return 0;
}
Figure 6-3. File Searching Using Multiple Processes
[View full size image]
