2010-09-20 55 views
5

我在寫一個C擴展,提供了Ruby和異步I/O庫之間的接口。當運行在我的代碼測試,我經常得到包括錯誤(但不限於):如何避免Ruby擴展中的跨線程違規?

[BUG] cross-thread violation in rb_thread_schedule() 

異步IO意味着我的C擴展需要傳遞的消息從多個線程(不是主要的解釋線程)與紅寶石。在這個過程中,我如何避免這些線程安全違規?

+0

Ruby 1.8.x或1.9.x? – llasram 2010-09-20 17:06:31

+0

我的擔心是1.8,但1.9也是相關的。 – 2010-09-20 22:26:40

回答

7

對於ruby 1.8.x來說,避免錯誤的唯一方法是顯而易見的 - 只從主解釋器線程調用Ruby/C API。我相信這也適用於Ruby 1.9.x,但我沒有使用它,也不知道它的本地線程支持如何改變。您不需要讓多個本地線程直接調用API,您需要使用生產者/消費者模式將來自輔助本機線程的請求傳遞到主解釋器線程中的代碼。理想情況下,這樣做不會不必要地阻塞其他Ruby綠色線程。如果你看看ruby的實現,那麼ruby的綠色線程調度器就是一個基本的select()循環。這表明了以下總體結構:

  • 創建管道或其他IPC機制,它提供了一個真實的select()可用文件描述符。
  • 生成本機線程併爲它們提供管道的寫入結束。
  • 在主解釋器線程中,輸入一個事件循環,在管道的讀取端調用rb_thread_wait_fd()。這將允許ruby綠色線程調度程序運行其他綠色線程。
  • 當您的輔助本機線程對主線程有請求時,它們將它們排隊並寫入管道,喚醒運行事件循環的綠色線程。

rb_io_sysread()什麼可能是在Ruby代碼庫的最簡單幹淨的IO-使用功能(執行IO#sysread)。

相關問題