Frage

Ich schreibe eine C-Erweiterung, eine Schnittstelle zwischen Ruby und einer asynchronen I / O-Bibliothek bereitstellt. Wenn die Tests über meinen Code ausgeführt wird, ich häufig bekommen Fehler einschließlich (aber nicht beschränkt auf):

[BUG] cross-thread violation in rb_thread_schedule()

Asynchronous IO bedeutet, meine C-Erweiterung benötigt, von mehreren Threads Nachrichten an Rubin liefern (nicht der Haupt Dolmetscher Gewinde). Wie vermeide ich diese Thread-Sicherheit Verletzungen im Prozess?

War es hilfreich?

Lösung

Für Rubin 1.8.x der einzige Weg, um den Fehler ist die offensichtlichste zu vermeiden - nur invoke der Ruby / C API vom Haupt Interpreter-Thread. Ich glaube, dass dies auch in Ruby 1.9.x gilt, aber ich habe nicht mit ihm gearbeitet und weiß nicht, wie seine native Thread-Unterstützung Dinge ändern könnte. Statt mehrere native Threads direkt aufrufen, um die API mit, müssen Sie den Erzeuger / Verbraucher-Muster verwenden Anforderungen von sekundären nativen Threads im Haupt Interpreter Thread, um Ihren Code zu liefern. Und im Idealfall dies tun, während nicht unnötig andere Ruby-grüne Fäden blockiert. Wenn man sich die Ruby-Implementierung aussieht, ist der Rubin grün Thread-Scheduler essentialy eine select() Schleife. Dies deutet auf die folgende Gesamtstruktur:

  • Erstellen Sie ein Rohr oder eine andere IPC-Mechanismus, der eine echte select()-able Dateideskriptors bietet.
  • Spawn native Threads und sie mit dem Schreibende des Rohres sorgen.
  • Im Haupt Interpreter Thread Geben eine Ereignisschleife, die auf der Lese rb_thread_wait_fd() Ende des Rohres aufruft. Dies wird der Rubin grün Thread-Scheduler ermöglicht andere grüne Fäden laufen zu lassen.
  • Wenn Sie Ihre sekundären nativen Threads Anfragen für den Haupt-Thread hat, Warteschlange sie sie und auch auf das Rohr schreiben, den grünen Faden Ihre Ereignisschleife aufwacht.

Siehe rb_io_sysread() (Implementierung von IO#sysread) für das, was ist wahrscheinlich die einfachste sauber IO-mit-Funktion in der Ruby-Code-Basis.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top