Является ли mutex С++ 11 совместимым с потоками, не созданными с С++ 11?

Я изучаю С++ 11 и столкнулся с проблемой потоковой передачи. Мой общий вопрос: существуют ли мьютексы С++ 11, совместимые с потоками, не созданными с использованием стандартных библиотек С++ 11?

Я хотел бы безопасно обмениваться информацией между потоком, созданным с С++ 11, и другим потоком, созданным сторонней библиотекой, в которой я не контролирую.

Например, мое приложение использует PortAudio, который создает собственный поток для вывода звука. Я не уверен, что он использует pthreads или специфичные для ОС библиотеки потоков, но я знаю, что PortAudio НЕ написан на С++ 11. Я хочу безопасно обмениваться данными между потоком GUI (с использованием потока С++ 11) и потоком PortAudio с использованием мьютекса.

Аналогично, могу ли я использовать мьютекс С++ 11 для синхронизации потоков QT QThreads и С++ 11?

Ответ 1

Очевидно, что стандарт С++ не дает никаких гарантий относительно совместимости с другими системами. Часть причин, по которым стандарты C и С++ добавили средства для потоковой передачи, заключались в стандартизации на одной системе потоковой передачи.

На практике ожидается, что библиотека потоков C и С++ построена для интеграции с системой потоковой обработки платформы, если таковая имеется. Например, на платформах, использующих pthreads, ожидание состоит в том, что pthreads используются там, где это необходимо, для создания стандартных средств потоковой обработки библиотек (насколько я знаю, нет никакого интерфейса pthreads для различных атомных операций, то есть стандартная библиотека может потребоваться предоставить свои собственные примитивы синхронизации).

Стандартные классы библиотеки обеспечивают доступ к базовому представлению с помощью методов native_handle(). Стандартная библиотека должна реализовывать то, что возвращается от них, и, например, если предоставляются типы pthreads, кажется безопасным предположить, что эта конкретная стандартная библиотека будет хорошо работать с pthreads.

Ответ 2

Являются ли мьютексы С++ 11 совместимыми с потоками, не созданными с использованием стандартных библиотек С++ 11?

Стандарт С++ не определяет "поток" как нечто, созданное только стандартной библиотекой С++.

1.10 Многопоточные исполнения и расписания данных [intro.multithread]

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

Итак, я бы пришел к выводу, что ответ на ваш вопрос "да".

Ответ 3

В стандарте С++ 11 указано, что мьютексы должны работать с любым "исполнительным агентом", включая разные библиотеки потоков. Вот некоторые релевантные цитаты из стандарта, которые, я думаю, однозначно отвечают на вопрос:

Требования к мьютексам

Объект mutex обеспечивает защиту от расы данных и позволяет безопасная синхронизация данных между исполнителями (30.2.5). исполняющему агенту принадлежит мьютекс с момента его успешного вызова функции блокировки, пока она не вызовет разблокировку.

Требования к типам блокировки

Агент исполнения - это объект, такой как поток, который может выполнять работу параллельно с другими исполнителями. [Примечание: Реализации или пользователи могут вводить другие виды агентов, таких как процессы или задачи пула потоков. -end note] Вызывающий агент определяется контекст, например. вызывающий поток, который содержит вызов, и т.д.

Ответ 4

Непостижимо, что реализация потоковой реализации С++ 11 будет несовместима с реализацией потоковой реализации платформы, поскольку любая практическая программа, использующая потоки С++ 11, будет вызывать библиотеки платформ, и эти библиотеки сами могут быть потоковыми или создавать потоки (к мьютексам, например).

Реализация библиотеки С++ 11 для потоков, конечно же, не обязана использовать библиотеку потоковых потоков высокого уровня (например, pthreads или потоки окон), но, вероятно, будет, для этой цели, как было упомянуто, существует std:: thread:: native_handle(), чтобы получить собственный дескриптор. Однако даже там, где он не использует встроенную реализацию высокого уровня, он должен будет использовать те же примитивы ядра низкого уровня внизу.

Во всех мыслимых обстоятельствах поэтому должно быть совершенно безопасно использовать мьютексы С++ 11 с экземплярами потоков, создаваемыми вызовами из библиотеки, и наоборот, и смешивать любые другие вызовы синхронизации библиотеки или С++. Там действительно могут быть случаи, когда это необходимо сделать. Например, библиотека С++ 11 в настоящее время не предоставляет пулы потоков или блокировки чтения и записи (общие мьютексы). Возможно, вы захотите использовать собственные блокировки чтения и записи с потоками, запущенными с использованием std:: thread, или используйте одну из многих реализаций пула потоков, предоставляемых сторонними библиотеками в вашей программе на С++.

Единственное предостережение, которое следует соблюдать, заключается в том, что попытка смешать потоки С++ 11 (которые на практике будут обязаны так или иначе использовать потоки ядра по причинам, упомянутым выше) с библиотеками потоков, которые не используют потоки ядра в все (например, библиотеки, основанные на зеленых потоках или "пользовательских" потоках), могут привести к неприятностям.

Edit: В подтверждение этого я замечаю, что в §30.3 из С++ 11 говорится, хотя и ненормативно, что "Эти потоки [std:: thread threads] предназначены для сопоставления" один к одному "с потоками операционной системы".