2012-11-12 83 views
4

我知道XInitThreads()將允許我從主線程以外的線程對X服務器執行調用,並且如果我想讓OpenGL calls from secondary threads using Qt支持Xlib中的併發線程是必要的。我對我的應用程序有這樣的需求,但在非常罕見的情況下。不幸的是,XInitThreads()需要在我的應用程序執行開始時調用,因此會影響它是否需要它或特定運行(如果我需要多線程OpenGL,我無法知道運行該應用程序之前是否支持)。XInitThreads()的缺點是什麼?

我很肯定,如果我無用地調用XInitThread(),應用程序的整體行爲將保持不變,但編程完全取決於折衷,而且我很確定多線程支持不是默認行爲Xlib的。

The man page表示建議單線程程序不調用此函數,但它不說明原因。調用XInitThreads()時的折衷是什麼?

回答

11

它會在每個顯示器上創建一個全局鎖定,因此每次調用Xlib都會執行鎖定/解鎖。如果你自己進行鎖定(使用自己的鎖,一次只保留一個線程的Xlib用法),那麼理論上鎖定開銷會減少,同時做很多Xlib的工作,然後放棄你的鎖。或者在實踐中,大多數工具包使用的模型根本不鎖定,只需要應用程序只在主UI線程中使用X.

由於許多Xlib調用都阻塞(它們等待來自服務器的回覆),因此鎖定爭用可能是個問題。

在顯示器上也有一些鎖定per-Xlib調用的語義痛苦;在線程A上的每個Xlib調用之間,理論上可以在線程B上創建任何其他Xlib調用。因此,就混淆顯示狀態而言,線程可以相互踩踏,儘管其中一個線程一次只能執行一次Xlib請求。也就是說,XInitThreads()可以防止由於併發顯式訪問而引起的崩潰/損壞,但它並不真正關注多線程共享X服務器連接的任何語義考慮。

我認爲需要從併發顯示訪問中創建自己的語義意義是人們不打擾XInitThreads per-Xlib調用鎖定的一個原因。因爲無論如何他們最終都會獲得應用程序級別或工具包級別的鎖定。

這裏的一種方法是在每個線程中打開一個單獨的顯示連接,這可以根據您正在做的事情做出決定。

另一種方法是使用更新的xcb API而不是Xlib; xcb從頭開始設計爲多線程和非阻塞。

歷史上也出現了一些錯誤,在XInitThreads()在某些OS/Xlib的版本,但我不記得任何細節,我記得看到那些去了。