2010-10-21 70 views
1

我已經創建了兩個類。一個用於輸入讀取(通過istream對象)和解析,另一個用於處理解析器的輸出。
其中每一個都有一個實例。
我有一個解析器運行在調用istream :: get()的循環中,然後根據輸入爲第二個對象創建命令。然後將這些命令放在第二個對象在單獨的線程中處理的隊列中。
現在很明顯,我最終需要能夠發送「退出」命令。這裏出現了這個問題:「Quit」命令需要結束解析循環,但我找不到解析器發出信號的方式,因爲它在istream :: get()中被捕獲。
我需要一種方法來喚醒它的方法,但我找不到任何...
我想通過創建某種類型的「終止序列」到istream對象(在這種情況下是cin)來自istream :: rdbuf()的ostream對象。但是這不起作用 - 在嘗試寫入緩衝區之後,badbit被設置。
在StackOverflow的另一個問題,我看到提到的Boost庫的asio類,但我寧願不依賴於第三方庫。
有沒有辦法從istream :: get()中喚醒線程 - 也就是說有沒有辦法從程序中寫入istream緩衝區(也許假設它實際上是cin)?
另一種方法是殺死我可以接受的線程,因爲在那個特定的地方不需要清理。但是,這怎麼做呢? (我依靠POSIX線程實現)如何釋放一個通過istream封鎖線程

回答

1

你將不得不依賴於除標準iostream類以外的東西,因爲它們不提供select()式的行爲。另外,殺死線程對於POSIX來說是不可能的(並且在Windows中完全破壞)。您可以通過pthread_cancel()發出取消請求,但就您的情況而言,它可能會卡住在不可取消的系統調用中。特別感興趣的是,read()可能或不可取消,具體取決於環境。 At least one environment說取消點可能發生在read(),雖然承認它是一個Windows POSIX層。另外,最近爲Leopard 10.5.1的Mac OS X在可取消性方面具有破壞read()的實施方式。

一旦過了這個障礙,您還必須考慮C++析構函數和pthread_cancel之間的uneasy relationship。並非所有的環境都保證會調用析構函數,因此在C++代碼中使用pthread_cancel時必須非常小心。

總之,對於中斷I/O,使用低級別的I/O和select():一個FD用於I/O,一個第二FD(由pipe()創建)用於信令。或者,如果您很勇敢,請使用AIO,但您最好使用高級界面,如Boost.Asio

+0

我確實嘗試了pthread_cancel()調用,但正如您所說,它根本不起作用或者相當不可靠。儘管析構函數可能不會成爲問題,因爲我可以將清理代碼放入另一個線程中。感謝參考選擇()雖然。我不知道那個。 – iolo 2010-10-22 12:10:05

1

這是在.NET中實現的任何機會嗎? - 如果是這樣,請看Reactive Framework。 它提供了一個非常優雅的方式來處理特別是取消他們在飛行中。 - 在此之上,你得到的LINQ擴展的非常可擴展庫,各種各樣的東西,比如緩衝,記憶化,郵編等..

我們用了很多的轉化(和解析)的流建模數據。

從Reative隊傑夫擁有不錯的博客大約Streaming and Reative here一個couble:

+0

嗯......我想我忘了那一點。 ;-)我在Mac上這樣做,但我希望代碼是可移植的。因此,我只想使用標準庫或任何posix調用。 – iolo 2010-10-22 00:02:06