Можно ли это сделать с помощью 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? Если нет, то я бы назвал ответ Габриэля Гонсалеса.