Unikanie rekursji podczas synchronicznego odczytu / zapisu portu?

108

Wszystkie operacje na portach w Rebol 3 są asynchroniczne. Jedynym sposobem, w jaki mogę znaleźć komunikację synchroniczną, jest dzwonienie wait.

Ale problem z wywołaniem wait w tym przypadku polega na tym, że sprawdza zdarzenia dla wszystkich otwartych portów (nawet jeśli nie znajdują się one w bloku portów przekazanym do oczekiwania). Następnie wywołują odpowiadające im programy obsługi zdarzeń, ale odczyt / zapis można wykonać w jednym z tych programów obsługi zdarzeń. Może to spowodować rekurencyjne wywołania „czekania”.

Jak mam to obejść?

Shixin Zeng
źródło
8
Właściwie nie wydaje mi się, aby było rozwiązanie tego problemu w obecnej implementacji R3, więc poszedłem dalej, aby dodać udoskonalenie "/ only" do "czekania", z którym będzie czekał tylko na portach przewidzianych do "czekania" , a tym samym unikaj wywołań rekurencyjnych. Zobacz moją prośbę o wycofanie na: github.com/rebol/rebol/pull/177
Shixin Zeng,
1
Z ciekawości, dlaczego potrzebujesz, aby był synchroniczny?
toadzky
1
Istnieje wiele sytuacji, w których kodowanie za pomocą portu synchronicznego jest znacznie łatwiejsze: załóżmy, że chcesz wysłać wiadomość e-mail za pomocą kliknięcia przycisku i zgłosić, czy się powiedzie, czy nie. O wiele łatwiej jest poczekać, aż się zakończy, zanim zrobisz cokolwiek innego.
Shixin Zeng
1
czy absolutnie musisz używać Rebol?
Rivenfall
1
Tak. W rzeczywistości jest to bardziej kwestia dotycząca Rebol 3 niż ogólnie komunikacji synchronicznej.
Shixin Zeng

Odpowiedzi:

1

Dlaczego nie utworzysz czegoś w rodzaju funkcji "bufora", aby otrzymywać wszystkie wiadomości z asynchronicznych wpisów i przetwarzać je jako FIFO (pierwszy na wejściu, pierwszy na wyjściu)?

W ten sposób możesz zachować właściwości Assync swoich portów i przetwarzać je w trybie synchronizacji.

David BS
źródło
0

w przypadkach, gdy występują tylko zdarzenia asynchroniczne i potrzebujemy synchronicznej odpowiedzi, uruchom licznik czasu lub uśpienie w celu przekroczenia limitu czasu, jeśli funkcja obsługi lub wymagany cel zostanie osiągnięty, powiedz true, w przeciwnym razie fałszywe i upewnij się, że zdarzenie zostanie anulowane / zresetowane dla to samo, jeśli jest krytyczne.

mkumar
źródło
0

Myślę, że istnieją 2 problemy projektowe (mogą być nieodłączne od dostępnych narzędzi / rozwiązań).

  1. Waitrobi za dużo - it will check events for all open ports. W zdrowym środowisku czekanie powinno być realizowane tylko wtedy, gdy jest to potrzebne: na urządzenie, na port, na gniazdo ... Tworzenie niepotrzebnych współzależności między współdzielonymi zasobami nie może się dobrze skończyć - zwłaszcza wiedząc, że współdzielone zasoby (nawet bez wzajemnych zależności) może powodować wiele problemów.

  2. Programy obsługi zdarzeń mogą robić za dużo. Procedura obsługi zdarzeń powinna być możliwie najkrótsza i powinna obsługiwać tylko zdarzenie. Jeśli robi więcej, oznacza to, że program obsługi robi za dużo - zwłaszcza jeśli korzysta z innych współdzielonych zasobów. W wielu sytuacjach przewodnik po prostu zapisuje dane, które w przeciwnym razie zostaną utracone; a praca asynchroniczna zrobi bardziej złożone rzeczy.

virolino
źródło
-1

Możesz po prostu użyć zamka. Cummunication1 może ustawić jakiś stan blokady globalnej, np. Za pomocą zmiennej (upewnij się, że jest bezpieczna dla wątków). locked = true. Następnie Communication2 może poczekać, aż zostanie odblokowany.

loop do
    sleep 10ms
    break if not locked
end
locked = true
handle_communication()
Rivenfall
źródło
1
W rzeczywistości jest to bardziej kwestia dotycząca Rebol 3 niż ogólnie komunikacji synchronicznej.
Shixin Zeng