Избежать рекурсии при чтении/записи порта синхронно?

Все операции с портами в Rebol 3 являются асинхронными. Единственный способ найти синхронную связь - вызов wait.

Но проблема с вызовом wait в этом случае заключается в том, что он будет проверять события для всех открытых портов (даже если они не находятся в портовом блоке, прошедшем для ожидания). Затем они называют свои обработчики обработчиков событий, но чтение/запись может выполняться в одном из этих обработчиков событий. Это может привести к рекурсивным вызовам "wait".

Как мне обойти это?

Ответ 1

в случаях, когда есть только асинхронные события, и мы нуждаемся в синхронном ответе, запускаем таймер или спящий режим для тайм-аута, если выполняется обработчик или требуемая цель, тогда скажем true, else false и убедитесь, что событие отменено / reset для того же, если критический.

Ответ 2

Почему вы не создаете своего рода функцию "Буфер", чтобы получать все сообщения из assyncronous записей и обрабатывать их как FIFO (first-in, first-out)?

Таким образом вы можете сохранить характеристики Assync ваших портов и обработать их в режиме синхронизации.

Ответ 3

Я думаю, что есть 2 проблемы дизайна (возможно, свойственные инструментам/решениям под рукой).

  1. Wait делает слишком много - it will check events for all open ports. В звуковой среде ожидание должно быть реализовано только там, где это необходимо: для каждого устройства, для каждого порта, для каждого сокета... Создание ненужных взаимозависимостей между общими ресурсами не может хорошо закончиться - особенно с учетом того, что общие ресурсы (даже без взаимозависимостей) может создать много проблем.

  2. Обработчики событий могут сделать слишком много. Обработчик события должен быть как можно короче, и он должен обрабатывать только событие. Если is делает больше, то обработчик делает слишком много - особенно если задействует другие общие ресурсы. Во многих ситуациях обработчик просто сохраняет данные, которые в противном случае будут потеряны; и асинхронная работа сделает более сложные вещи.

Ответ 4

Вы можете просто использовать блокировку. Cummunication1 может установить некоторое глобальное состояние блокировки, то есть с переменной (убедитесь, что она потокобезопасна). locked = true. Тогда Communication2 может ждать, пока он не разблокируется.

loop do
    sleep 10ms
    break if not locked
end
locked = true
handle_communication()