10

GNU Cライブラリは最近pthreadキャンセルにDWARF2アンワインドを使用しているため、C ++例外とpthreadキャンセルクリーンアップハンドラーの両方が、途中で必要に応じて自動オブジェクトのデストラクタを呼び出す共通の呼び出しフレームアンワインドプロセスを通じて呼び出されます。ただし、私が知る限り、(POSIX)スレッドとC ++の間の相互作用を指定する標準はまだありません。おそらく、移植性を望むアプリケーションは、キャンセルクリーンアップコンテキストから例外をスローすることは、呼び出すのと同じくらい未定義であると想定する必要がありますlongjmp。それらのうち、重要なデストラクタを持つライブ自動オブジェクトを持つスレッドをキャンセルすることも未定義の動作です。

この相互作用に対処するために進行中の標準化プロセスはありますか、それとも将来的には未定義であると予想されるものですか?C ++ 11には、スレッドサポートでPOSIXスレッドキャンセルに類似した概念がありますか?

4

1 に答える 1

13

WG14(C)、WG15(POSIX)、およびWG21(C ++)を含むISO / IEC SC22に参加している人として、私は簡単な答えはノーであり、C++例外とスレッドキャンセルはお互いに会うことはないだろうと言うことができますすぐに時間。C11とC++11はスレッドのキャンセルについて言及しておらず、次の主要な標準が約10年後にリリースされる前に、スレッドのキャンセルを認識する可能性は非常に低いです。

より長い答えは、標準がどのように機能するかに帰着します。基本的に、ISOは誰もが同意できることを標準化することしかできず、スレッドのキャンセルに関しては人々は同意しません。すべてのキャンセル可能なシステムコールの前に状態をダンプしなければならない実行のスレッドの全体的な考えは、現代のソフトウェア開発の精神全体に反します。C ++の例外スローとは異なり、スレッドのキャンセルは、追加の処理を明示的に排除するthread_terminate(self)の呼び出しと同じであると定義されているため(多くの実装ではキャンセルハンドラーでさえ確実に呼び出されないため)、コンパイラの最適化に大きな問題が発生します。スレッドキャンセルサポーターがそれが悪い解決策であることに同意しないとは思わない。

問題は、唯一の適切な代替手段は、非同期完了バリアントを使用してPOSIX i /oAPIを再発行することです。そして、それに関する問題は、POSIXの実装が異なれば非同期完了の考え方も大きく異なることです。つまり、カーネル待機キューの標準について合意することすらできないので、それが達成されるまで、非同期I /OAPIは遠い道のりです。次の標準TC/TRのためにカーネル待機キューを移動する提案がありますが、提案されたオブジェクトは意図的に非常に単純化されています。

C11 / C ++ 11で試みたのは、スレッドAPIが常に非ブロッキングバージョンを持つことです-そこには、非ブロッキングを実行できないAPIが1つだけあります。それはthread_join()です(そこにあります)はthread_timedjoin())ではなく、Austin Working Groupの承認を得た後、個人的に正誤表を提出する予定です。他のすべての場合、効率的ではないがプログラムは正しいポーリングを行うものをいつでも構築できます。

長期的には、個人的に言えば、C++と同様のセマンティクスに従ってCに例外処理を追加する十分な理由があります。オブジェクトのサポートは必ずしも必要ではありませんが(実際には、非仮想オブジェクトをCに個人的に追加することもサポートします)、スタックアンワインドラムダ関数呼び出しの概念はあります。これにより、適切に定義されたメカニズムを使用して、スレッドキャンセルなどのハックを形式化できます。また、風を書くときにアンワインドを書くことができるため、フォールトトレラントCの記述がはるかに簡単かつ安全になり、古いCが新しいCと透過的に相互運用できるようになります。

例外処理内から例外をスローすることに関して、私は個人的に、terminate()を常に自動呼び出すよりも良いことをする必要があると思います。巻き戻しは新しいオブジェクトの構築、または実際に他の例外スローの原因となる可能性があるため、プロセスを終了する前にスタック全体を巻き戻すためにあらゆる合理的な試みが行われることを個人的に強く望んでいます。

したがって、要するに、POSIXスレッドのキャンセルは未定義と見なされ続けると予想され、長期的には、より良いものを優先して非推奨になる可能性が高くなります。

ところで、一般的にPOSIXスレッドのキャンセルは実装間で非常に移植性が低いため、POSIXスレッドのキャンセルを使用するコードは、非POSIXAPIを使用する場合と同じプラットフォーム固有の動作に効果的に依存しています。コードを移植可能にしたい場合は、POSIXスレッドキャンセルを使用しないでください。代わりに、魔法の「今すぐスレッドを停止してください」ファイル記述子を含むselect()またはpoll()を使用してください。私自身のC++コードには、この魔法のファイル記述子をテストして特別なC++例外をスローするシステムAPIラッパーマクロが実際にあります。これにより、Windowsを含むすべてのプラットフォームで同じ動作が保証されます。

于 2012-02-27T16:04:00.650 に答える