Харт Джонсон М.
Шрифт:
} RECORD;
#define RECSIZE sizeof (RECORD)
typedef RECORD * LPRECORD;
typedef struct _THREADARG { /* Аргумент потока */
DWORD iTh; /* Номер потока: 0, 1, 2, … */
LPRECORD LowRec; /* Младшая часть указателя записи */
LPRECORD HighRec; /* Старшая часть указателя записи */
} THREADARG, *PTHREADARG;
static int KeyCompare(LPCTSTR, LPCTSTR);
static DWORD WINAPI ThSort(PTHREADARG pThArg);
static DWORD nRec; /* Общее число записей, подлежащих сортировке. */
static HANDLE* ThreadHandle;
int _tmain(int argc, LPTSTR argv[]) {
HANDLE hFile;
LPRECORD pRecords = NULL;
DWORD FsLow, nRead, LowRecNo, nRecTh, NPr, ThId, iTh;
BOOL NoPrint;
int iFF, iNP;
PTHREADARG ThArg;
LPTSTR StringEnd;
iNP = Options(argc, argv, _T("n"), &NoPrint, NULL);
iFF = iNP + 1;
NPr = _ttoi(argv[iNP]); /* Количество потоков. */
hFile = CreateFile(argv[iFF], GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
FsLow = GetFileSize(hFile, NULL);
nRec = FsLow / RECSIZE; /* Общее число записей. */
nRecTh = nRec / NPr; /* Количество записей на один поток. */
/* Распределить память для аргументов потока и массива дескрипторов и выделить в памяти место для файла. Считать весь файл. */
ThArg = malloc(NPr * sizeof(THREADARG));
/* Аргументы потоков. */
ThreadHandle = malloc(NPr * sizeof(HANDLE));
pRecords = malloc(FsLow + sizeof(TCHAR));
ReadFile(hFile, pRecords, FsLow, &nRead, NULL);
CloseHandle(hFile);
LowRecNo = 0; /* Создать потоки, выполняющие сортировку. */
for (iTh = 0; iTh < NPr; iTh++) {
ThArg[iTh].iTh = iTh;
ThArg[iTh].LowRec = pRecords + LowRecNo;
ThArg[iTh].HighRec = pRecords + (LowRecNo + nRecTh);
LowRecNo += nRecTh;
ThreadHandle[iTh] = (HANDLE)_beginthreadex (NULL, 0, ThSort, &ThArg[iTh], CREATE_SUSPENDED, &ThId);
}
for (iTh = 0; iTh < NPr; iTh++) /* Запустить все потоки сортировки. */
ResumeThread(ThreadHandle [iTh]);
WaitForSingleObject(ThreadHandle[0], INFINITE);
for (iTh = 0; iTh < NPr; iTh++) CloseHandle(ThreadHandle [iTh]);
StringEnd = (LPTSTR)pRecords + FsLow;
*StringEnd = '\0';
if (!NoPrint) printf("\n%s", (LPCTSTR)pRecords);
free(pRecords);
free(ThArg);
free(ThreadHandle);
return 0;
} /* Конец tmain. */
static VOID MergeArrays(LPRECORD, LPRECORD);
DWORD WINAPI ThSort(PTHREADARG pThArg) {
DWORD GrpSize = 2, RecsInGrp, MyNumber, TwoToI = 1;
LPRECORD First;
MyNumber = pThArg->iTh;
First = pThArg->LowRec;
RecsInGrp = pThArg->HighRec – First;
qsort(First, RecsInGrp, RECSIZE, KeyCompare);
while ((MyNumber % GrpSize) == 0 && RecsInGrp < nRec) {
/* Объединить слиянием отсортированные массивы. */
WaitForSingleObject(ThreadHandle[MyNumber + TwoToI], INFINITE);
MergeArrays(First, First + RecsInGrp);
RecsInGrp *= 2;
GrpSize *= 2;