Есть ли какое-либо движение к определению взаимодействия исключений С++ и аннулирования pthread?

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

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

Ответ 1

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

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

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

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

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

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

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

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