Что означает С++ 11 как "поток"?

В С++ 11 есть понятие потоков. Например, он определяет новый спецификатор хранилища thread_local и указывает, что для переменных с этим спецификатором хранилища "есть отдельный объект или ссылка на поток" [basic.stc.thread].

Что считается "потоком" для этой цели? Это только потоки, созданные с использованием стандартной библиотеки потоков (т.е. Тех, которые представлены объектами std::thread)? Что относительно потоков, созданных другими способами (например, с помощью pthreads непосредственно в Linux)? Что делать, если я использую библиотеку, которая обеспечивает потоки пользовательского пространства - каждый из них получает свои собственные копии объектов thread_local (я действительно не вижу, как это можно реализовать)?

Если ответ "это реализация, определяемая реализацией, которая рассматривается как поток для целей, таких как thread_local", может ли кто-нибудь дать пример того, как это известная реализация определяет это?

Ответ 1

Из-за этих кавычек подсчитываются только компоненты из библиотеки поддержки потоков, или main, которые стандартные состояния выполняются в своем потоке выполнения.

1 Следующие подразделы описывают компоненты для создания и управления потоками (1.10), выполняют взаимное исключение и сообщают условия и значения между потоками, как показано в таблице 148.

Ссылка на 1.10 подразумевает, что речь идет о потоках.

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

Поэтому мне кажется, что потоки относятся только к потокам stdlib (что означает std:: thread и все, что делает библиотека поддержки потоков). Конечно, thread_local во многих случаях может работать с собственными потоками (особенно, если вы рассматриваете в конкретной системе, у вас обычно нет более одного выбора для реализации потоков), но насколько я могу сказать, что стандарт не делает гарантия.

Ответ 2

С++ 11 §1.10/1 определяет термины:

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

Курсивные термины означают, что это является окончательным. Вы можете утверждать, что это определение математически недостаточно, потому что каждый вызов функции определяет новый поток, но это явно неправильно. Они означают максимальный единый поток управления, иначе ненормативная нота отменит эффект нормативного "рекурсивно включающего" текста.

С точки зрения основного языка, это просто случайно, что std::thread вызывает такую ​​вещь.

Что делать, если я использую библиотеку, которая предоставляет потоки пользовательского пространства - каждый из них получает свои собственные копии объектов thread_local (я действительно не вижу, как это можно реализовать)?

Невозможно написать такую ​​библиотеку без вызовов ядра. По всей вероятности, все потоки в вашем процессе уже представляют собой абстракцию высокого уровня, такую ​​как pthreads, только для удовлетворения ядра. Стандартная библиотека С++, вероятно, написана против собственной библиотеки потоков, чтобы "просто работать" без дополнительного клея.

Например, объекты thread_local инициализируются при первом доступе, а не при запуске каждого нового потока, поэтому компилятор просто должен вставить запрос на основе pthread_self для доступа и, возможно, инициализации. Инициализация будет регистрировать деструктор с помощью средства pthread_cleanup.

Что определяется реализацией, является ли совместимая с С++ ранее существовавшая родная библиотека. Предположим, что они обеспечивают это, и что-то, чего пожелают клиенты, все другие библиотеки потоков, построенные на нем, будут автоматически совместимы, запретив некоторые другие конфликты.

Ответ 3

Стандарт не описывает, как ведут себя потоки, созданные другими библиотеками и системными вызовами. Они, насколько это касается стандарта, undefined в своем поведении. Другого пути в С++ не существует, чтобы создать несколько потоков: такие библиотеки или системные вызовы делают вещи, которые не стандартизованы стандартом С++.

Теперь каждый такой библиотечный и системный вызов будет вести себя так, как это определено его собственными спецификациями. Довольно часто С++ std::thread будет даже построен поверх таких библиотек или системных вызовов. Как точно работает взаимодействие, не указано.