in src/tools/closetest/closetest.cpp [664:841]
static int doParent(std::deque<std::wstring> argv)
{
int numBatches = 4;
int dir = 0;
bool useJob = false;
bool useGapProcess = false;
int allocChunk = 0;
bool useSiblings = false;
bool noRealloc = false;
// Parse arguments
shift(argv); // discard the program name.
while (!argv.empty())
{
const auto arg = shift(argv);
const auto hasNext = !argv.empty();
if (arg == L"--help" || arg == L"-h")
{
usage();
exit(0);
}
else if (arg == L"-n" && hasNext)
{
numBatches = shiftInt(argv);
}
else if (arg == L"-d" && hasNext)
{
const auto next = shift(argv);
if (next == L"forward")
{
dir = 1;
}
else if (next == L"backward")
{
dir = 2;
}
else if (next == L"alternate")
{
dir = 3;
}
else if (next == L"none")
{
dir = 0;
}
else
{
fprintf(stderr, "error: unrecognized -d argument: %ls\n", next.c_str());
exit(1);
}
}
else if (arg == L"--gap")
{
useGapProcess = true;
}
else if (arg == L"--no-gap")
{
useGapProcess = false;
}
else if (arg == L"--alloc" && hasNext)
{
const auto next = shift(argv);
allocChunk = (int)(_wtof(next.c_str()) * 1024.0 * 1024.0);
}
else if (arg == L"-m" && hasNext)
{
const auto next = shift(argv);
if (next == L"pipe")
{
useJob = false;
}
else if (next == L"job")
{
useJob = true;
}
else
{
fprintf(stderr, "error: unrecognized -m argument: %ls\n", next.c_str());
exit(1);
}
}
else if (arg == L"--graph" && hasNext)
{
const auto next = shift(argv);
if (next == L"tree")
{
useSiblings = false;
}
else if (next == L"list")
{
useSiblings = true;
}
else
{
fprintf(stderr, "error: unrecognized --graph argument: %ls\n", next.c_str());
exit(1);
}
}
else if (arg == L"--log" && hasNext)
{
const auto next = shift(argv);
std::wstring pipename(L"\\\\.\\pipe\\");
pipename.append(next);
g_hLogging = CreateFileW(pipename.c_str(), GENERIC_WRITE, FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, 0, nullptr);
if (g_hLogging != INVALID_HANDLE_VALUE)
{
g_pipestr = next;
}
else
{
fprintf(stderr, "error: pipe cannot be opened: %ls\n", next.c_str());
exit(1);
}
}
else if (arg == L"--delay" && hasNext)
{
const auto next = shift(argv);
const long ms = std::stol(next);
std::this_thread::sleep_for(std::chrono::milliseconds(ms));
}
else if (arg == L"--no-realloc")
{
noRealloc = true;
}
else
{
usage();
fprintf(stderr, "\nerror: unrecognized argument: %ls\n", arg.c_str());
exit(1);
}
}
// Decide which children to start.
std::vector<std::wstring> spawnList;
std::vector<HANDLE> handles;
for (int i = 0; i < numBatches; ++i)
{
if (dir == 0)
{
genChild(i + 1, L"", allocChunk, spawnList);
}
if (dir & 1)
{
genBatch(true, useJob, useGapProcess, allocChunk, spawnList, handles);
}
if (dir & 2)
{
genBatch(false, useJob, useGapProcess, allocChunk, spawnList, handles);
}
}
// Spawn the children.
if (!noRealloc)
{
FreeConsole();
AllocConsole();
}
if (useSiblings)
{
spawnSiblings(GetCurrentProcessId(), spawnList);
}
else
{
spawnChildTree(GetCurrentProcessId(), spawnList);
}
for (auto h : handles)
{
CloseHandle(h);
}
// Wait until we're killed.
dumpConsoleProcessList();
Sleep(300 * 1000);
return 0;
}