2010-09-20 8 views
5

Tôi đang viết một phần mở rộng C, cung cấp một giao diện giữa Ruby và một thư viện I/O không đồng bộ. Khi chạy các bài kiểm tra qua mã của tôi, tôi thường xuyên nhận được lỗi bao gồm (nhưng không giới hạn):Làm cách nào để tránh vi phạm nhiều luồng trong tiện ích mở rộng Ruby?

[BUG] cross-thread violation in rb_thread_schedule() 

Asynchronous IO nghĩa mở rộng C tôi sẽ cần phải cung cấp các thông điệp để ruby ​​từ nhiều chủ đề (không phải là chủ đề thông dịch viên chính) . Làm cách nào để tránh các vi phạm an toàn chủ đề này trong quá trình xử lý?

+0

Ruby 1.8.x hoặc 1.9.x? – llasram

+0

Sự quan tâm của tôi là 1,8, nhưng 1,9 cũng có liên quan. –

Trả lời

7

Đối với ruby ​​1.8.x cách duy nhất để tránh lỗi là lỗi hiển nhiên - chỉ gọi API Ruby/C từ chuỗi thông dịch chính. Tôi tin rằng điều này cũng áp dụng cho ruby ​​1.9.x, nhưng tôi chưa từng làm việc với nó và không biết cách hỗ trợ luồng gốc của nó có thể thay đổi mọi thứ như thế nào. Thay vì có nhiều luồng gốc trực tiếp gọi API, bạn cần phải sử dụng mẫu nhà sản xuất/người tiêu dùng để phân phối các yêu cầu từ các chuỗi gốc của bạn tới mã của bạn trong luồng thông dịch chính. Và lý tưởng làm điều này trong khi không cần thiết ngăn chặn các chuỗi màu xanh lá cây Ruby khác. Nếu bạn nhìn vào việc thực hiện ruby, bộ lập lịch chuỗi màu xanh lá cây của ruby ​​là cần thiết một vòng lặp select(). Điều này gợi ý cấu trúc tổng thể sau:

  • Tạo một đường ống hoặc cơ chế IPC khác cung cấp mô tả tệp thực sự select().
  • Tạo các chuỗi gốc tự nhiên và cung cấp cho chúng phần cuối của ống.
  • Trong chuỗi trình thông dịch chính, nhập vòng lặp sự kiện gọi rb_thread_wait_fd() vào đầu đọc của ống. Điều này sẽ cho phép trình lập lịch trình chuỗi màu xanh lá cây của ruby ​​chạy các luồng màu xanh lá cây khác.
  • Khi chuỗi gốc thứ cấp của bạn có yêu cầu cho chuỗi chính, chúng xếp hàng chúng và cũng viết vào đường ống, đánh thức chuỗi màu xanh lá cây đang chạy vòng lặp sự kiện của bạn.

Xem rb_io_sysread() (triển khai IO#sysread) cho những gì có lẽ là chức năng sử dụng IO sạch đơn giản nhất trong cơ sở mã ruby.