Можно ли это сделать с помощью STM?
Отказ от ответственности: это легко можно сделать, используя MVar ()
как простой мьютекс. Я просто любопытно посмотреть, можно ли это сделать с помощью STM.
Я хочу сделать следующее атомарно:
-
Прочитайте некоторые переменные.
-
Решите, какой I/O выполнить, на основе того, что я только что прочитал.
-
Выполните ввод/вывод.
-
Запишите результаты в переменных.
Для конкретности предположим, что я хочу отслеживать, сколько байтов ввода я прочитал, и притвориться, что я достиг EOF после того, как было потрачено определенное количество байтов. (ОК, позволяя двум потокам читать один и тот же файл одновременно, вероятно, является фальшивым, что нужно сделать в первую очередь, но пойдите со мной на этом...)
Очевидно, что это не может быть одна транзакция STM; там I/O посередине. Очевидно, было бы также неправильно иметь это как две несвязанные транзакции. (Два потока могли видеть, что остался один байт квоты, и оба решили прочитать этот байт.)
Есть ли хорошее решение этой проблемы? Или STM просто неправильный инструмент для этой задачи?
Ответы
Ответ 1
Я бы сказал, что STM не может этого сделать, и это специально. Часть кода STM может быть перезапущена несколько раз в разных местах, если транзакция откат. Что произойдет, если вы запустите свою транзакцию, она выполняет операцию ввода-вывода и затем откатывается при записи результатов в переменных?
По этой причине вычисления STM должны быть чистыми, только с добавлением STM-примитивов, таких как изменяемые переменные STM и массивы.
Ответ 2
Используйте TVar Bool
с именем consistent
, чтобы отслеживать, выполняется ли ваше действие ввода-вывода. Перед выполнением действия ввода-вывода, которое вы устанавливаете в соответствии с False
, и после запуска действия ввода-вывода, установите consistent
на True
. Затем любое действие, зависящее от значений тех переменных STM, которые вы изменяете, просто ставит это предложение в начале:
do b <- readTVar consistent
check b
...
Это гарантирует, что эти действия видят только согласованное представление изменяемых переменных и не будут выполняться во время выполнения операции ввода-вывода.
Ответ 3
Я думаю, вы ищете stm-io-hooks пакет.
Что бы вы на самом деле не хотели делать - можно ли было бы выразить это с точки зрения STM abort/retry semantics? Другими словами: Можете ли вы выполнить откат и повторить действие IO?
Если нет, то я бы назвал ответ Габриэля Гонсалеса.