Чтение онлайн

на главную - закладки

Жанры

Системное программирование в среде Windows

Харт Джонсон М.

Шрифт:

 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;

TwoToI *= 2;

 }

 _endthreadex(0);

 return 0; /* Подавить вывод предупреждающих сообщений. */

}

static VOID MergeArrays(LPRECORD p1, LPRECORD p2) {

 DWORD iRec = 0, nRecs, i1 = 0, i2 = 0;

 LPRECORD pDest, p1Hold, pDestHold;

 nRecs = p2 – p1;

 pDest = pDestHold = malloc(2 * nRecs * RECSIZE);

 p1Hold = p1;

 while (i1 < nRecs && i2 < nRecs) {

if (KeyCompare((LPCTSTR)p1, (LPCTSTR)p2) <= 0) {

memcpy(pDest, p1, RECSIZE);

i1++;

p1++;

pDest++;

} else {

memcpy(pDest, p2, RECSIZE);

i2++;

p2++;

pDest++;

}

 }

 if (i1 >= nRecs) memcpy(pDest, p2, RECSIZE * (nRecs – i2));

 else memcpy(pDest, p1, RECSIZE * (nRecs – i1));

 memcpy(p1Hold, pDestHold, 2 * nRecs * RECSIZE);

 free (pDestHold);

 return;

}
 

Производительность

В приложении В представлены результаты сортировки файлов большого размера, содержащих записи длиной 64 байта, для случаев использования одной, двух и четырех потоков. SMP-системы позволяют получать значительно лучшие результаты. Упомянутый принцип "разделяй и властвуй" обеспечивает нечто большее, чем просто стратегию проектирования алгоритмов; он также служит ключом к использованию потоков и SMP. Результаты для однопроцессорных систем могут быть различными в зависимости от остальных характеристик системы. В системах с ограниченным объемом памяти (то есть объема физической памяти не достаточно для того, чтобы наряду с ОС и другими активными процессами в ней уместился весь файл) использование нескольких потоков увеличивает время сортировки, поскольку потоки состязаются между собой в захвате доступной физической памяти. С другой стороны, если памяти имеется достаточно, то многопоточный вариант может привести к повышению производительности и в случае однопроцессорных систем. Кроме того, как следует из приложения В, получаемые результаты существенно зависят от начального распределения данных.

Локальные

области хранения потоков

Потокам могут требоваться собственные, независимо распределяемые и управляемые ими области памяти, защищенные от других потоков того же процесса. Одним из методов создания таких областей является вызов функции CreateThread (или _beginthreadex) с параметром lpvThreadParm, указывающим на структуру данных, уникальную для каждого потока. После этого поток может распределять память для дополнительных структур данных и получать доступ к ним через указатель lpvThreadParm. Эта методика используется в программе 7.1.

Кроме того, Windows предоставляет локальные области хранения потоков (Thread Local Storage, TLS), обеспечивающие каждый из потоков собственным массивом указателей. Организация TLS показана на рис. 7.3.

Индексы (строки) TLS первоначально не распределены, но в любой момент времени можно добавлять новые строки и освобождать существующие, причем минимально возможное число строк для любого процесса определяется значением TLS_MINIMUM_AVAILABLE (равным, по крайней мере, 64). Число столбцов может изменяться по мере создания новых потоков и завершения существующих.

Сначала мы рассмотрим управление индексами TLS. Логическим пространством для этого служит основной поток, но управлять индексами может любой поток.

Функция TlsAlloc возвращает распределенный индекс (> 0) или –1 (0xFFFFFFFF) в случае отсутствия доступных индексов. 

DWORD TlsAlloc(VOID)

BOOL TlsFree(DWORD dwIndex)
 

Рис. 7.3. Локальные области хранения потоков в контексте процесса

Каждый отдельный поток может выбирать и устанавливать значения (указатели типа void), связанные с ее областью памяти, используя индексы TLS.

Программист всегда должен убеждаться в том, что параметр индекса TLS является действительным, то есть что он был распределен с помощью функции TlsAlloc, но не был освобожден. 

LPVOID TlsGetValue(DWORD dwTlsIndex)

BOOL TlsSetValue(DWORD dwTlsIndex, LPVOID lpTlsValue)
 

TLS предоставляют удобный механизм организации памяти, являющейся глобальной в контексте потока, но недоступной другим потокам. Обычные глобальные хранилища разделяются всеми потоками. Несмотря на то что ни один поток не может получить доступа к TLS другого потока, любой поток может уничтожить индекс TLS другого потока, вызвав функцию TlsFree, так что этой функцией следует пользоваться с осторожностью. TLS часто используются DLL в качестве замены глобальной памяти библиотеки; в результате этого каждый поток получает в свое распоряжение собственную глобальную память. Кроме того, TLS обеспечивают вызывающим программам удобный способ взаимодействия с функциями DLL, и именно этот способ применения TLS является наиболее распространенным. В качестве примера в главе 12 (программа 12.4) TLS используются для создания библиотеки DLL с многопоточной поддержкой; другим важным элементом этого решения являются уведомления DLL о присоединении/отсоединении потоков и процессов путем вызова функции DllMain (глава 5). 

Приоритеты процессов и потоков и планирование выполнения

Ядро Windows всегда запускает тот из потоков, готовых к выполнению, который обладает наивысшим приоритетом. Поток не является готовым к выполнению, если он находится в состоянии ожидания, приостановлен или блокирован по той или иной причине.

Потоки получают приоритеты на базе классов приоритета своих процессов. Как обсуждалось в главе б, первоначально функцией CreateProcess устанавливаются четыре класса приоритета, каждый из которых имеет базовый приоритет (base priority):

Поделиться:
Популярные книги

Камень Книга седьмая

Минин Станислав
7. Камень
Фантастика:
фэнтези
боевая фантастика
6.22
рейтинг книги
Камень Книга седьмая

Я сделаю это сама

Кальк Салма
1. Магический XVIII век
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Я сделаю это сама

Кровь на эполетах

Дроздов Анатолий Федорович
3. Штуцер и тесак
Фантастика:
альтернативная история
7.60
рейтинг книги
Кровь на эполетах

Сыночек в награду. Подари мне любовь

Лесневская Вероника
1. Суровые отцы
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Сыночек в награду. Подари мне любовь

Кодекс Крови. Книга ХII

Борзых М.
12. РОС: Кодекс Крови
Фантастика:
боевая фантастика
попаданцы
5.00
рейтинг книги
Кодекс Крови. Книга ХII

Найди меня Шерхан

Тоцка Тала
3. Ямпольские-Демидовы
Любовные романы:
современные любовные романы
короткие любовные романы
7.70
рейтинг книги
Найди меня Шерхан

Идеальный мир для Лекаря 4

Сапфир Олег
4. Лекарь
Фантастика:
фэнтези
юмористическая фантастика
аниме
5.00
рейтинг книги
Идеальный мир для Лекаря 4

Релокант. По следам Ушедшего

Ascold Flow
3. Релокант в другой мир
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Релокант. По следам Ушедшего

Мир-о-творец

Ланцов Михаил Алексеевич
8. Помещик
Фантастика:
альтернативная история
5.00
рейтинг книги
Мир-о-творец

Протокол "Наследник"

Лисина Александра
1. Гибрид
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Протокол Наследник

Кодекс Охотника. Книга VII

Винокуров Юрий
7. Кодекс Охотника
Фантастика:
фэнтези
попаданцы
аниме
4.75
рейтинг книги
Кодекс Охотника. Книга VII

Попаданка в семье драконов

Свадьбина Любовь
Попаданка в академии драконов
Любовные романы:
любовно-фантастические романы
7.37
рейтинг книги
Попаданка в семье драконов

Новые горизонты

Лисина Александра
5. Гибрид
Фантастика:
попаданцы
технофэнтези
аниме
сказочная фантастика
фэнтези
5.00
рейтинг книги
Новые горизонты

Скрываясь в тени

Мазуров Дмитрий
2. Теневой путь
Фантастика:
боевая фантастика
7.84
рейтинг книги
Скрываясь в тени