Rekursion beim synchronen Lesen / Schreiben eines Ports vermeiden?

108

Alle Portoperationen in Rebol 3 sind asynchron. Die einzige Möglichkeit, eine synchrone Kommunikation durchzuführen, ist das Anrufen wait.

Das Problem beim Aufrufen von wait besteht in diesem Fall darin, dass Ereignisse für alle offenen Ports überprüft werden (auch wenn sie sich nicht in dem zum Warten übergebenen Portblock befinden). Dann rufen sie ihre antwortenden Ereignishandler auf, aber in einem dieser Ereignishandler kann ein Lese- / Schreibvorgang durchgeführt werden. Dies könnte zu rekursiven Aufrufen zum "Warten" führen.

Wie komme ich darum herum?

Shixin Zeng
quelle
8
Eigentlich glaube ich nicht, dass es in der aktuellen R3-Implementierung eine Lösung dafür gibt, also habe ich "wait" um eine "/ only" -Verfeinerung erweitert, mit der nur auf die Ports gewartet wird, die für "wait" bereitgestellt werden. und vermeiden Sie so die rekursiven Aufrufe. Siehe meine Pull-Anfrage unter: github.com/rebol/rebol/pull/177
Shixin Zeng
1
Warum muss es aus Neugier synchron sein?
Toadzky
1
Es gibt viele Situationen, in denen das Codieren mit synchronem Port viel einfacher ist: Angenommen, Sie möchten eine E-Mail mit einem Klick auf eine Schaltfläche senden und melden, ob dies erfolgreich ist oder fehlschlägt. Es ist viel einfacher zu warten, bis es fertig ist, bevor Sie etwas anderes tun.
Shixin Zeng
1
Müssen Sie unbedingt Rebol verwenden?
Rivenfall
1
Ja. Dies ist eigentlich eher eine Frage zu Rebol 3 als zur synchronen Kommunikation im Allgemeinen.
Shixin Zeng

Antworten:

1

Warum erstellen Sie nicht eine Art "Puffer" -Funktion, um alle Nachrichten von assynkronen Einträgen zu empfangen und als FIFO (First-In, First-Out) zu verarbeiten?

Auf diese Weise können Sie die Assync-Eigenschaften Ihrer Ports beibehalten und im Synchronisierungsmodus verarbeiten.

David BS
quelle
0

In Fällen, in denen es nur asynchrone Ereignisse gibt und wir eine synchrone Antwort benötigen, starten Sie einen Timer oder schlafen Sie für eine Zeitüberschreitung. Wenn der Handler oder das erforderliche Ziel erreicht ist, sagen Sie true, andernfalls false und stellen Sie sicher, dass das Ereignis für das Ereignis abgebrochen / zurückgesetzt wird gleich wenn kritisch.

mkumar
quelle
0

Ich denke, dass es zwei Designprobleme gibt (möglicherweise im Zusammenhang mit den vorliegenden Tools / Lösungen).

  1. Waitmacht zu viel - it will check events for all open ports. In einer soliden Umgebung sollte das Warten nur dort implementiert werden, wo es benötigt wird: pro Gerät, pro Port, pro Socket ... Das Erstellen unnötiger Abhängigkeiten zwischen gemeinsam genutzten Ressourcen kann nicht gut enden - insbesondere wenn Sie wissen, dass gemeinsam genutzte Ressourcen (auch ohne Abhängigkeiten) vorhanden sind. kann viele Probleme verursachen.

  2. Die Event-Handler tun möglicherweise zu viel. Ein Ereignishandler sollte so kurz wie möglich sein und nur das Ereignis behandeln. Wenn dies mehr bewirkt, tut der Handler zu viel - insbesondere, wenn andere gemeinsam genutzte Ressourcen beteiligt sind. In vielen Situationen speichert der Handler nur die Daten, die sonst verloren gehen. und ein asynchroner Job erledigt die komplexeren Dinge.

Virolino
quelle
-1

Sie können einfach ein Schloss verwenden. Cummunication1 kann einen globalen Sperrstatus festlegen, dh mit einer Variablen (stellen Sie sicher, dass dieser threadsicher ist). locked = true. Dann kann Communication2 warten, bis es entsperrt ist.

loop do
    sleep 10ms
    break if not locked
end
locked = true
handle_communication()
Rivenfall
quelle
1
Dies ist eigentlich eher eine Frage zu Rebol 3 als zur synchronen Kommunikation im Allgemeinen.
Shixin Zeng