На этом рисунке мы отмечаем, что структура Pthread поддерживается системой (вероятно, библиотекой потоков), но фактически собственные данные потока, которые мы размещаем в памяти с помощью функции malloc
readline
). Все, что делает функция pthread_setspecific
, — это установка указателя для данного ключа в структуре Pthread на выделенную область памяти. Аналогично, действие функции pthread_getspecific
сводится к возвращению этого указателя.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. Поток номер
readline
, используя и модифицируя свои собственные данные.Один вопрос, который мы пока не рассмотрели, заключается в следующем: что происходит, когда поток завершает свое выполнение? Если поток вызвал функцию readline
pthread_key_create
, одним из аргументов этой функции является указатель на pkey
для данного потока, вызывая соответствующую функцию-деструктор для каждого непустого указателя pkey
. Под «соответствующим деструктором» мы понимаем указатель на функцию, хранящийся в массиве Key
с рис. 26.2. Таким образом осуществляется освобождение памяти, занимаемой собственными данными потока, когда выполнение потока завершается.Первые две функции, которые обычно вызываются при работе с собственными данными потока, — это pthread_once
pthread_key_create
.#include
int pthread_once(pthread_once_t *
int pthread_key_create(pthread_key_t *
Функция 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 */
}