私は2つのクラスを作成しました。1 つは入力の読み取り (istream オブジェクトによる) と解析用で、もう 1 つはパーサーの出力の処理用です。
それぞれのインスタンスが 1 つあります。
istream::get() を呼び出すループでパーサーを実行し、入力に基づいて 2 番目のオブジェクトのコマンドを作成します。これらのコマンドは、2 番目のオブジェクトが別のスレッドで処理するキューに置かれます。
これで、最終的に「Quit」コマンドを送信できるようにする必要があることは明らかです。ただし、ここで問題が発生します。「Quit」コマンドは解析ループも終了する必要がありますが、istream::get() 内でキャッチされているため、終了する必要があることをパーサーに通知する方法が見つかりません。
そのメソッドからウェイクアップする方法が必要ですが、見つかりません...
istream::rdbuf() から ostream オブジェクトを作成することにより、istream オブジェクト (この場合は cin) にある種の「終了シーケンス」を書き込むことを考えました。しかし、それはうまくいきません - バッファへの書き込みを試みた後、badbit が設定されます。
StackOverflow の別の質問で、Boost ライブラリの asio クラスが言及されているのを見ましたが、サードパーティのライブラリには依存したくありません。
istream::get() からスレッドをウェイクアップする方法はありますか?つまり、プログラム内から istream バッファーに書き込む方法はありますか?
別のアプローチは、その特定の場所でクリーンアップが必要ないため、許容できるスレッドを強制終了することです。しかし、これはどのように行うことができますか?(私は POSIX スレッドの実装に依存しています)
2 に答える
これが.NETに実装されている可能性はありますか?-もしそうなら、リアクティブフレームワークを見てください。これは、ストリームを処理し、特にその場でそれらをキャンセルする非常にエレガントな方法を提供します。
- これに加えて、バッファリング、メモ化、Zipなど、あらゆる種類のものに対応するLinq拡張機能の非常に拡張可能なライブラリを入手できます。
ストリーミングされたデータの変換(および解析)、モデリングによく使用します。
ReativeチームのJeffは、ストリーミングとReativeに関するすばらしいブログをここにまとめています。
標準の iostream クラス以外のものに依存する必要があります。これらは iostream のselect()
動作を提供しないためです。
また、スレッドを強制終了することは POSIX では不可能です (Windows では完全に壊れています)。経由でキャンセル リクエストを発行できpthread_cancel()
ますが、この場合、キャンセルできないシステム コールでスタックしている可能性があります。read()
環境によっては、キャンセルできる場合とできない場合があります。少なくとも 1 つの環境では、Windows POSIX レイヤーであることは確かですが、でキャンセル ポイントが発生する可能性があると言われています。また、最近のLeopard 10.5.1read()
の Mac OS X では、キャンセル機能に関して実装が壊れていました。read()
このハードルを越えると、C++ デストラクタと pthread_cancel の間の厄介な関係についても考慮する必要があります。すべての環境でデストラクタが呼び出されることが保証されているわけではないため、C++ コードで pthread_cancel を使用する場合は細心の注意を払う必要があります。
つまり、割り込み可能な I/O には、低レベルの I/O と を使用しselect()
ます。1 つの fd を I/O 用に、2 つ目の fd (によって作成されたpipe()
) をシグナリング用に使用します。または、勇気がある場合はAIOを使用しますが、おそらくBoost.Asioなどの高レベルのインターフェイスを使用する方がよいでしょう。