Есть ли движение в направлении определения взаимодействия исключений C ++ и отмены pthread? - PullRequest
10 голосов
/ 25 февраля 2012

Библиотека GNU C использует размотку DWARF2 для отмены pthread в наши дни, так что и исключения C ++, и обработчики очистки отмены pthread вызываются через общий процесс раскручивания фрейма вызова, который по мере необходимости вызывает деструкторы для автоматических объектов. Однако, насколько я могу судить, до сих пор нет стандарта, определяющего взаимодействие между потоками (POSIX) и C ++, и, предположительно, приложение, желающее быть переносимым, должно предполагать, что исключение исключений из контекстов очистки отмены так же не определено, как и вызов longjmp из них, и что отмена потока, у которого есть живые автоматические объекты с нетривиальными деструкторами, также является неопределенным поведением.

Идет ли какой-либо процесс стандартизации, касающийся этого взаимодействия, или можно ожидать, что он будет неопределенным в будущем? Есть ли в C ++ 11 аналогичное понятие для отмены потока POSIX в его поддержке потока?

1 Ответ

13 голосов
/ 27 февраля 2012

Как кто-то, кто сидит на ISO / IEC SC22, который включает WG14 (C), WG15 (POSIX) и WG21 (C ++), я могу сказать вам, что быстрый ответ - нет, исключения C ++ и отмена потока не будут видныдруг друга в ближайшее время.C11 и C ++ 11 не упоминают об отмене потоков, и весьма вероятно, если не крайне маловероятно, что они узнают это до следующего основного выпуска стандартов примерно через десять лет.

Более длинный ответ сводится к тому, как работают стандарты,По сути, ISO может стандартизировать только то, о чем каждый может договориться, и люди не соглашаются, когда речь идет об отмене ветки.Сама идея того, что потоку выполнения приходится выгружать состояние перед каждым отменяемым системным вызовом, идет вразрез с идеями современной разработки программного обеспечения.Это вызывает огромные проблемы для оптимизации компилятора, потому что в отличие от бросков исключений в C ++, отмена потока определяется так же, как и вызов thread_terminate (self), который явно исключает выполнение каких-либо дополнительных действий (и даже обработчики отмены не вызывают надежного вызова во многих реализациях), иЯ не думаю, что сторонники отмены потока не согласятся с тем, что это плохое решение.

Проблема в том, что единственная правильная альтернатива - это переиздание API ввода / вывода POSIX с асинхронными вариантами завершения.И проблема в том, что разные реализации POSIX думают об асинхронном завершении по-разному.Я имею в виду, что мы даже не можем договориться о стандарте для очередей ожидания ядра, поэтому до достижения этого асинхронного API ввода-вывода еще далеко.У меня есть предложение сделать некоторые движения в очередях ожидания ядра для следующих стандартов TC / TR, но предложенный объект намеренно предельно упрощен.

То, что мы пытались сделать в C11 / C ++ 11, эточтобы потоковый API всегда имел неблокируемые версии - там есть только один API, который не может быть выполнен неблокирующим, это thread_join () (нет thread_timedjoin ()), и я планирую лично отправить исправления начто после того, как я получу одобрение Рабочей группы Остина.Во всех других случаях всегда можно создать что-то, что опрашивает, что неэффективно, но является корректной программой.

В долгосрочной перспективе, лично говоря, я вижу много веских причин для добавления обработки исключений в C после аналогичныхсемантика в C ++.У вас не будет обязательной поддержки объектов (я бы на самом деле поддерживал добавление не-виртуальных объектов в C слишком лично), но у вас была бы концепция стека, разматывающего вызовы лямбда-функций.Это позволило бы нам формализовать такие хаки, как отмена потока, с помощью правильно определенного механизма.Это также делает написание отказоустойчивого C намного проще и безопаснее, позволяя записывать раскручивание при написании ветрового кода и позволяет старому C прозрачно взаимодействовать с новым C.

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

Итак, вкратце, ожидайте, что отмена потока POSIX будет по-прежнему рассматриваться как неопределенная, и есть большие шансы, что в долгосрочной перспективе он станет устаревшим в пользу чего-то лучшего.

Кстати, как правило, отмена потока POSIX крайне непереносима между реализациямиТаким образом, любой код, который использует отмену потока POSIX, эффективно полагается на специфичное для платформы поведение, которое идентично использованию не-POSIX API.Если вы хотите, чтобы ваш код был переносимым, не используйте отмену потоков POSIX.Вместо этого используйте select () или poll (), включая магический дескриптор файла «пожалуйста, остановите поток сейчас».В моем собственном коде C ++ у меня фактически есть макрос-обертка системного API, который проверяет этот магический дескриптор файла и выдает специальное исключение C ++.Это обеспечивает одинаковое поведение на всех платформах, включая Windows.

...