Читаем UNIX: разработка сетевых приложений полностью

Частично осложнения возникают по той причине, что во всех книгах, где идет речь о потоках, описание собственных данных потоков дается по образцу стандарта Pthreads. Пары ключ-значение и ключи рассматриваются в них как непрозрачные объекты. Мы описываем собственные данные потоков в терминах индексов и указателей, так как обычно в реализациях в качестве ключей используются небольшие положительные целые числа (индексы), а значение, ассоциированное с ключом, — это просто указатель на область памяти, выделяемую потоку с помощью функции malloc.

В каждой системе поддерживается ограниченное количество объектов собственных данных потоков. В POSIX требуется, чтобы этот предел не превышал 128 (на каждый процесс), и в следующем примере мы используем именно это значение. Система (вероятно, библиотека потоков) поддерживает один массив структур (которые мы называем структурами Key) для каждого процесса, как показано на рис. 26.2.

Рис. 26.2. Возможная реализация собственных данных потока

Флаг в структуре Key указывает, используется ли в настоящий момент данный элемент массива. Все флаги инициализируются как указывающие на то, что элемент не используется. Когда поток вызывает функцию pthread_key_create для создания нового элемента собственных данных потока, система отыскивает в массиве структур Key первую структуру, не используемую в настоящий момент. Индекс этой структуры, который может иметь значение от 0 до 127, называется ключом и возвращается вызывающему потоку как результат выполнения функции. О втором элементе структуры Key, так называемом указателе-деструкторе, мы поговорим чуть позже.

В дополнение к массиву структур Key, общему для всего процесса, система хранит набор сведений о каждом потоке процесса в структуре Pthread. Частью этой структуры является массив указателей, состоящий из 128 элементов, который мы называем pkey. Это показано на рис. 26.3.

Рис. 26.3. Информация, хранящаяся в системе для каждого потока

Все элементы массива pkey инициализируются пустыми указателями. Эти 128 указателей являются «значениями», ассоциированными с каждым из 128 «ключей» процесса.

Когда мы с помощью функции pthread_key_create создаем ключ, система сообщает нам фактическое значение ключа (индекс). Затем каждый поток может сохранить значение (указатель), связанное с этим ключом, и, как правило, каждый поток получает этот указатель в виде возвращаемого значения функции malloc. Частично путаница с собственными данными потока обусловлена тем, что указатель в паре ключ-значение играет роль значения, но сами собственные данные потока — это то, на что указывает данный указатель.

Теперь мы перейдем к примеру применения собственных данных потока, предполагая, что наша функция readline использует их для хранения информации о состоянии каждого потока при последовательных обращениях к ней. Вскоре мы покажем код, выполняющий эту задачу, в котором функция readline модифицирована так, чтобы реализовать представленную далее последовательность шагов.

1. Запускается процесс, и создается несколько потоков.

2. Один из потоков вызовет функцию readline первой, а та, в свою очередь, вызовет функцию phtread_key_create. Система отыщет первую неиспользуемую структуру Key (см. рис. 26.2) и возвратит вызывающему процессу ее индекс. В данном примере мы предполагаем, что индекс равен 1.

Мы будем использовать функцию pthread_once, чтобы гарантировать, что функция pthread_key_create вызывается только первым потоком, вызвавшим функцию readline.

3. Функция readline вызывает функцию pthread_getspecific, чтобы получить значение pkey[1] («указатель» на рис. 26.3 для ключа, имеющего значение 1) для данного потока, но эта функция возвращает пустой указатель. Тогда функция readline вызывает функцию malloc для выделения памяти, которая необходима для хранения информации о каждом потоке при последовательных вызовах функции readline. Функция readline инициализирует эти области памяти по мере надобности и вызывает функцию pthread_setspecific, чтобы установить указатель собственных данных потока (pkey[1]), соответствующий данному ключу, на только что выделенную область памяти. Мы показываем этот процесс на рис. 26.4, предполагая, что вызывающий поток — это поток с номером 0 в данном процессе.

Рис. 26.4. Соответствие между областью памяти, выделенной функцией malloc, и указателем собственных данных потока

Перейти на страницу:

Все книги серии Мастер-класс

Секреты резьбы по дереву
Секреты резьбы по дереву

Изделия из древесины и материалов, имитирующих ее текстуру, привычным образом окружают нас в повседневной жизни, поэтому мы относимся к ней как к чему-то обыденному. Но как только ее коснется умелая рука мастера резьбы по дереву, рождается произведение искусства и раскрываются такие качества древесины, как богатая фактура, разнообразие цветов, особая теплота. Эта книга поможет читателю открыть для себя удивительный мир творчества и познать секреты резьбы по дереву. Автор надеется, что начинающие резчики найдут в ней интересный и полезный материал, который позволит им стать мастерами. В приложении представлены рисунки орнаментов и различных узоров, которые на первых порах можно копировать, а по мере приобретения навыка на их основе разрабатывать свои образцы.

Галина Алексеевна Серикова

Сделай сам / Хобби и ремесла / Руководства / Дом и досуг / Словари и Энциклопедии

Похожие книги