Читаем Linux API. Исчерпывающее руководство полностью

void *pthread_getspecific(pthread_key_t key);

Возвращает указатель или NULL, если с ключом не связаны данные уровня потока

Аргумент value, передающийся функции pthread_setspecific(), обычно является указателем на блок памяти, ранее выделенный вызывающим потоком. При завершении потока этот указатель будет передан в функцию-деструктор для текущего ключа.

Аргумент value не обязательно должен быть указателем на блок памяти. Он может представлять собой некое скалярное значение, которое можно привести к типу void *. В этом случае в ранее сделанном вызове функции pthread_key_create() аргумент destructor должен равняться NULL.

На рис. 31.3 показана типичная реализация структуры данных, которая используется для хранения value. На этой диаграмме подразумевается, что элемент pthread_keys[1] был выделен функции с именем myfunc(). Программный интерфейс Pthreads предоставляет массив указателей на блоки данных каждого отдельного потока. Элементы этих массивов напрямую соответствуют элементам глобального массива pthread_keys, показанного на рис. 31.2. Функция pthread_setspecific() привязывает каждый элемент массива к соответствующему ключу вызывающего потока.

При создании потока указатели на все его данные инициализируются значением NULL. Это означает, что, когда поток впервые вызывает нашу функцию, он должен сначала сделать вызов pthread_getspecific(), чтобы проверить, имеет ли он значение, связанное с ключом. Если такого значения нет, функция выделяет блок памяти и сохраняет указатель на него с помощью вызова pthread_setspecific(). В следующем разделе эта процедура будет продемонстрирована на примере реализации потокобезопасной разновидности функции strerror().



Рис. 31.3.Структура данных, которая используется для реализации указателей на данные уровня потока (ДОП)


31.3.4. Использование программного интерфейса для работы с данными уровня потока

При первом знакомстве со стандартной функцией strerror() (см. раздел 3.4) мы отмечали, что она может вернуть указатель на статически выделенную строку. Это означает, что данная функция может не быть потокобезопасной. На нескольких следующих страницах мы рассмотрим стандартную реализацию strerror() и затем увидим, как сделать ее потокобезопасной с помощью данных уровня потока.

Во многих реализациях UNIX, включая Linux, функция strerror(), входящая в состав стандартной библиотеки С, является потокобезопасной. Она выбрана в качестве демонстрации, потому что стандарт SUSv3 не требует применять к ней правила потоковой безопасности; к тому же ее реализация послужит простым примером использования данных уровня потока.

В листинге 31.1 показана простая реализация strerror(), которая не является потокобезопасной. Она задействует две глобальные переменные, объявленные библиотекой glibc: одна, _sys_errlist, представляет собой массив указателей на строки, соответствующие номерам ошибок в errno (хотя элемент _sys_errlist[EINVAL], к примеру, указывает на строку Invalid operation), а другая, _sys_nerr, указывает, сколько элементов находится в _sys_errlist.


Листинг 31.1. Реализация strerror() без учета потоковой безопасности

threads/strerror.c

#define _GNU_SOURCE /* Получаем объявления '_sys_nerr'

и '_sys_errlist' из файла */

#include

#include  /* Получаем объявление strerror() */


#define MAX_ERROR_LEN 256 /* Максимальная длина строки,

возвращаемой функцией strerror() */


static char buf[MAX_ERROR_LEN]; /* Статически выделенный итоговый буфер */


char *

strerror(int err)

{

if (err < 0 || err >= _sys_nerr || _sys_errlist[err] == NULL) {

snprintf(buf, MAX_ERROR_LEN, "Unknown error %d", err);

} else {

strncpy(buf, _sys_errlist[err], MAX_ERROR_LEN — 1);

buf[MAX_ERROR_LEN — 1] = '\0'; /* Завершаем строку символом '\0' */

}


return buf;

}

threads/strerror.c

На примере данной программы можно продемонстрировать последствия того, что реализация strerror() из листинга 31.1 пренебрегает потоковой безопасностью. Эта программы вызывает strerror() из двух разных потоков, но выводит возвращаемое значение только после того, как оба потока завершили выполнение этой функции. И хотя каждый поток передает функции strerror() разные значения (EINVAL и EPERM), полученный результат будет следующим (при условии, если мы скомпилируем и скомпонуем программу с версией strerror() из листинга 31.1):

$ ./strerror_test

Main thread has called strerror()

Other thread about to call strerror()

Other thread: str (0x804a7c0) = Operation not permitted

Main thread: str (0x804a7c0) = Operation not permitted

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

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

C++ Primer Plus
C++ Primer Plus

C++ Primer Plus is a carefully crafted, complete tutorial on one of the most significant and widely used programming languages today. An accessible and easy-to-use self-study guide, this book is appropriate for both serious students of programming as well as developers already proficient in other languages.The sixth edition of C++ Primer Plus has been updated and expanded to cover the latest developments in C++, including a detailed look at the new C++11 standard.Author and educator Stephen Prata has created an introduction to C++ that is instructive, clear, and insightful. Fundamental programming concepts are explained along with details of the C++ language. Many short, practical examples illustrate just one or two concepts at a time, encouraging readers to master new topics by immediately putting them to use.Review questions and programming exercises at the end of each chapter help readers zero in on the most critical information and digest the most difficult concepts.In C++ Primer Plus, you'll find depth, breadth, and a variety of teaching techniques and tools to enhance your learning:• A new detailed chapter on the changes and additional capabilities introduced in the C++11 standard• Complete, integrated discussion of both basic C language and additional C++ features• Clear guidance about when and why to use a feature• Hands-on learning with concise and simple examples that develop your understanding a concept or two at a time• Hundreds of practical sample programs• Review questions and programming exercises at the end of each chapter to test your understanding• Coverage of generic C++ gives you the greatest possible flexibility• Teaches the ISO standard, including discussions of templates, the Standard Template Library, the string class, exceptions, RTTI, and namespaces

Стивен Прата

Программирование, программы, базы данных
1С: Бухгалтерия 8 с нуля
1С: Бухгалтерия 8 с нуля

Книга содержит полное описание приемов и методов работы с программой 1С:Бухгалтерия 8. Рассматривается автоматизация всех основных участков бухгалтерии: учет наличных и безналичных денежных средств, основных средств и НМА, прихода и расхода товарно-материальных ценностей, зарплаты, производства. Описано, как вводить исходные данные, заполнять справочники и каталоги, работать с первичными документами, проводить их по учету, формировать разнообразные отчеты, выводить данные на печать, настраивать программу и использовать ее сервисные функции. Каждый урок содержит подробное описание рассматриваемой темы с детальным разбором и иллюстрированием всех этапов.Для широкого круга пользователей.

Алексей Анатольевич Гладкий

Программирование, программы, базы данных / Программное обеспечение / Бухучет и аудит / Финансы и бизнес / Книги по IT / Словари и Энциклопедии
C# 4.0: полное руководство
C# 4.0: полное руководство

В этом полном руководстве по C# 4.0 - языку программирования, разработанному специально для среды .NET, - детально рассмотрены все основные средства языка: типы данных, операторы, управляющие операторы, классы, интерфейсы, методы, делегаты, индексаторы, события, указатели, обобщения, коллекции, основные библиотеки классов, средства многопоточного программирования и директивы препроцессора. Подробно описаны новые возможности C#, в том числе PLINQ, библиотека TPL, динамический тип данных, а также именованные и необязательные аргументы. Это справочное пособие снабжено массой полезных советов авторитетного автора и сотнями примеров программ с комментариями, благодаря которым они становятся понятными любому читателю независимо от уровня его подготовки. Книга рассчитана на широкий круг читателей, интересующихся программированием на C#.Введите сюда краткую аннотацию

Герберт Шилдт

Программирование, программы, базы данных