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

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

Жанры

UNIX: разработка сетевых приложений
Шрифт:

4. Другой поток, например поток с номером

n
, вызывает функцию
readline
, возможно, в тот момент, когда поток с номером 0 все еще находится в стадии выполнения функции
readline
.

Функция

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

5. Функция

readline
вызывает функцию
pthread_getspecific
для получения значения указателя
pkey[1]
для данного потока, но возвращается пустой указатель. Тогда поток вызывает функцию
malloc
и
функцию
pthread_setspecific
, как и в случае с потоком номер 0, инициализируя элемент собственных данных потока, соответствующий этому ключу (1). Этот процесс иллюстрирует рис. 26.5.

Рис. 26.5. Структуры данных после того, как поток n инициализировал свои собственные данные

6. Поток номер nпродолжает выполнять функцию

readline
, используя и модифицируя свои собственные данные.

Один вопрос, который мы пока не рассмотрели, заключается в следующем: что происходит, когда поток завершает свое выполнение? Если поток вызвал функцию

readline
, эта функция выделила в памяти область, которая должна быть освобождена по завершении выполнения потока. Для этого используется указатель-деструктор, показанный на рис. 26.2. Когда поток, создающий элемент собственных данных, вызывает функцию
pthread_key_create
, одним из аргументов этой функции является указатель на функцию-деструктор. Когда выполнение потока завершается, система перебирает массив
pkey
для данного потока, вызывая соответствующую функцию-деструктор для каждого непустого указателя
pkey
. Под «соответствующим деструктором» мы понимаем указатель на функцию, хранящийся в массиве
Key
с рис. 26.2. Таким образом осуществляется освобождение памяти, занимаемой собственными данными потока, когда выполнение потока завершается.

Первые две функции, которые обычно вызываются при работе с собственными данными потока, — это

pthread_once
и
pthread_key_create
.

#include <pthread.h>

int pthread_once(pthread_once_t * onceptr, void (* init)(void));

int pthread_key_create(pthread_key_t * keyptr, void (* destructor)(void * value));

Обе функции возвращают: 0 в случае успешного выполнения, положительное значение Exxx в случае ошибки

Функция

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

Функция

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

Обычно эти две функции используются следующим образом (если игнорировать возвращение ошибок):

pthread_key_t rl_key;

pthread_once_t rl_once = PTHREAD_ONCE_INIT;

void readline_destructor(void *ptr) {

free(ptr);

}

void readline_once(void) {

pthread_key_create(&rl_key, readline_destructor);

}

ssize_t readline(...) {

...

pthread_once(&rl_once, readline_once);

if ((ptr = pthread_getspecific(rl_key)) == NULL) {

ptr = Malloc(...);

pthread_setspecifiс(rl_key, ptr);

/*
инициализация области памяти, на которую указывает ptr */

}

...

/* используются значения, на которые указывает ptr */

}

Каждый раз, когда вызывается функция

readline
, она вызывает функцию
pthread_once
. Эта функция использует значение, на которое указывает ее аргумент-указатель
onceptr
(содержащийся в переменной
rl_once
), чтобы удостовериться, что функция
init
вызывается только один раз. Функция инициализации
readline_once
создает ключ для собственных данных потока, который хранится в
rl_key
и который функция
readline
затем использует в вызовах функций
pthread_getspecific
и
pthread_setspecific
.

Функции

pthread_getspecific
и
pthread_setspecific
используются для того, чтобы получать и задавать значение, ассоциированное с данным ключом. Это значение представляет собой тот указатель, который показан на рис. 26.3. На что указывает этот указатель — зависит от приложения, но обычно он указывает на динамически выделяемый участок памяти.

#include <pthread.h>

void *pthread_getspecific(pthread_key_t key);

Возвращает: указатель на собственные данные потока (возможно, пустой указатель)

int pthread_setspecific(pthread_key_t key, const void * value);

Возвращает: 0 в случае успешного выполнения, положительное значение Exxx в случае ошибки

Обратите внимание на то, что аргументом функции

pthread_key_create
является указатель на ключ (поскольку эта функция хранит значение, присвоенное ключу), в то время как аргументами функций
get
и
set
являются сами ключи (которые, скорее всего, представляют собой небольшие целые числа, как уже говорилось).

Пример: функция readline, использующая собственные данные потока

В этом разделе мы приводим полный пример использования собственных данных потока, преобразуя оптимизированную версию функции

readline
из листинга 3.12 к виду, безопасному в многопоточной среде, не изменяя последовательность вызовов.

В листинге 26.5 показана первая часть функции: переменные

pthread_key_t
и
pthread_once_t
, функции
readline_destructor
и
readline_once
и наша структура
Rline
, которая содержит всю информацию, нужную нам для каждого потока.

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

Не кровный Брат

Безрукова Елена
Любовные романы:
эро литература
6.83
рейтинг книги
Не кровный Брат

Релокант

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

Гром над Тверью

Машуков Тимур
1. Гром над миром
Фантастика:
боевая фантастика
5.89
рейтинг книги
Гром над Тверью

Ненастоящий герой. Том 1

N&K@
1. Ненастоящий герой
Фантастика:
боевая фантастика
попаданцы
рпг
5.00
рейтинг книги
Ненастоящий герой. Том 1

Попаданка

Ахминеева Нина
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Попаданка

Беглец

Кораблев Родион
15. Другая сторона
Фантастика:
боевая фантастика
попаданцы
рпг
5.00
рейтинг книги
Беглец

Приручитель женщин-монстров. Том 6

Дорничев Дмитрий
6. Покемоны? Какие покемоны?
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Приручитель женщин-монстров. Том 6

Неудержимый. Книга IX

Боярский Андрей
9. Неудержимый
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Неудержимый. Книга IX

Я еще не князь. Книга XIV

Дрейк Сириус
14. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я еще не князь. Книга XIV

Измена. За что ты так со мной

Дали Мила
1. Измены
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. За что ты так со мной

Измена. Испорченная свадьба

Данич Дина
Любовные романы:
современные любовные романы
короткие любовные романы
5.00
рейтинг книги
Измена. Испорченная свадьба

Приручитель женщин-монстров. Том 4

Дорничев Дмитрий
4. Покемоны? Какие покемоны?
Фантастика:
юмористическое фэнтези
аниме
5.00
рейтинг книги
Приручитель женщин-монстров. Том 4

Курсант: назад в СССР 9

Дамиров Рафаэль
9. Курсант
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Курсант: назад в СССР 9

Лорд Системы 12

Токсик Саша
12. Лорд Системы
Фантастика:
фэнтези
попаданцы
рпг
5.00
рейтинг книги
Лорд Системы 12