[英]Kill a blocked Boost::Thread
我正在編寫一個應用程序,它阻止來自兩個istreams
輸入。
從istream
讀取是一個同步(阻塞)調用,因此,我決定創建兩個Boost::thread
來進行讀取。
這些線程中的任何一個都可以到達“結束”(基於接收到的一些輸入),並且一旦達到“結束”,兩個輸入流都停止接收。 不幸的是,我不知道哪個會這樣做。
因此,我不能在兩個線程上join()
,因為只有一個線程(不能預先確定哪個)將實際返回(解除阻塞)。
我必須以某種方式強迫對方退出,但它被阻止等待輸入,所以它本身不能決定是時候返回(條件變量或什么不是)。
他們是一種方式:
istream
為“失敗”,或 注意:
istreams
是cin
編輯:
謝謝!
我不認為有跨平台的方法,但pthread_cancel應該是你想要的。 使用boost線程,您可以從線程獲取native_handle ,並在其上調用pthread_cancel。
另外一種更好的方法可能是在多個文件上使用與asa相當的boost asio 。 這樣一個線程將被阻塞等待輸入,但它可能來自任一輸入流。 我不知道用iostream做這樣的事是多么容易。
就在這里!
boost::thread::terminate()
將根據您的規范完成工作。
它將導致目標線程拋出異常。 假設它沒有被捕獲,堆棧將正確解除所有資源並終止線程執行。
終止不是即時的。 (無論如何,錯誤的線程正在運行。)
它發生在預定義的條件下 - 當你調用boost::this_thread::sleep();
時,最方便的就是你boost::this_thread::sleep();
,你可以讓那個線程定期做。
如果一個提升線程在一個i / o操作上阻塞(例如cin>>whatever
), boost::thread::terminate()
將不會boost::thread::terminate()
該線程。 cin
i / o不是有效的終止點。 趕上22。
在linux上,我使用pthread_signal(SIGUSR1),因為它會中斷阻塞IO。 我在移植代碼時發現,在Windows上沒有這樣的調用。 套接字讀取調用中只有一個已棄用的。 在Windows中,您必須明確定義將中斷阻塞調用的事件。 所以沒有這樣的東西(AFAIK)作為中斷阻塞IO的通用方法。
boost.thread設計通過管理良好識別的中斷點來處理此問題。 我不太了解boost.asio,似乎你不想依賴它。 如果您不想重構使用非阻塞范例,那么您可以做的是在非阻塞(輪詢)和阻塞IO之間使用某些東西。 這是做什么的(偽代碼?):
while(!stopped && !interrupted)
{
io.blockingCall(timeout);
if(!stopped && !interrupted)
{
doSomething();
}
}
然后你打斷你的兩個線程並加入他們......
也許你的情況更簡單? 如果你有一個知道一個線程結束的主線程你只需要關閉另一個線程的IO?
編輯:順便說一下,我對最終解決方案感興趣...
我自己也遇到了類似的問題並且已經達到了這個問題,這個問題的其他一些讀者可能會覺得有用:
假設您正在使用帶有wait()命令的條件變量,重要的是要知道在Boost中,wait()語句是一個自然的中斷點。 因此,只需使用wait語句在代碼周圍放置一個try / catch塊,並允許函數在catch塊中正常終止。
現在,假設你有一個帶有線程指針的容器,迭代你的線程指針並在每個線程上調用interrupt(),然后是join()。
現在,所有線程都將正常終止,任何與Boost相關的內存清理都應該干凈利落。
似乎線程無法幫助您以簡單的方式執行您想要的操作。 如果Boost.Asio不符合您的喜好,請考慮使用select()
。
我們的想法是獲取兩個文件描述符,並使用select()
告訴您哪些文件具有可用的輸入。 cin
文件描述符通常是STDIN_FILENO
; 如何獲取另一個取決於您的具體情況(如果它是一個文件,只需open()
它而不是使用ifstream
)。
在循環中調用select()
以找出要讀取的輸入,以及何時停止,只需退出循環。
很晚,但是在Windows中(對於那些讓這些東西重新出現的VMS或RSX的前身),我會使用類似ReadFileEx的東西,一個完成例程,在完成時發出信號,如果讀取需要提前取消,則使用CancelIO。
Linux / BSD有一個完全不同的底層API,並不靈活。 使用pthread_kill發送信號對我有用,這將停止讀/打開操作。
對於每個平台,恕我直言,值得在這個領域實現不同的代碼。
您可以隨時嘗試加入線程,而不是嘗試殺死線程,如果失敗,則加入另一個線程。 (假設您將始終能夠加入至少兩個線程中的一個)。
在boost:thread中你正在尋找timed_join函數。
但是,如果你想查看正確的答案,那就是使用非阻塞的io和定時等待。 允許您獲得同步io的流結構,同時不阻塞異步io。
你談論從istream中讀取形式,但是istream只是一個接口。 對於stdin,您可以只關閉stdin文件描述符來中斷讀取。 至於另一個,這取決於你從哪里讀...
在Windows下,使用QueueUserAPC對引發異常的proc進行排隊。 這種方法對我來說很好。
但是 :我剛剛發現在win32上提升互斥鎖等不是“可警告”,因此QueueUserAPC無法中斷它們。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.