lean4 icon indicating copy to clipboard operation
lean4 copied to clipboard

feat: `modifyM`/`modifyGetM` for `IO.Ref`

Open tydeu opened this issue 11 months ago • 4 comments

Adds IO.Ref.modfyM / IO.Ref.modifyGetM which are monadic variants of IO.Ref.modify (ST.Prim.Ref.modify) / IO.Ref.modifyGet (ST.Prim.Ref.modifyGet). Like them, it uses ST.Prim.Ref.take to atomically modify the reference via busy-waiting, but allow users to perform BaseIO actions within the critical section. This is safe because BaseIO / ST σ α actions do not throw exceptions. Without these utilities, to modify a reference while preforming I/O, one needs to use IO.Mutex. Thus, this provides a lightweight alternative for users.

The outstanding question here is whether this is good idea or if users should be expected to use IO.Mutex if they wish to modify a reference while performing I/O.

tydeu avatar Mar 09 '24 21:03 tydeu

Mathlib CI status (docs):

One potential issue is that you can get deadlocks using modify this way, right?

mhuisi avatar Mar 11 '24 09:03 mhuisi

@mhuisi Could you elaborate? I do not see how this introduces more possibility of deadlock than IO.Ref.modify and/or IO.Mutex. The example I can think of is that if you wait on a thread within the modifyM that is also waiting to modify the reference. But the same issue appears with IO.Mutex, so it does not seem to surprising.

tydeu avatar Mar 11 '24 11:03 tydeu

A common access pattern if modify allows IO would be to use modify on one IO.Ref and within that use modify on another IO.Ref. If another call site uses these modify calls in switched order, you may get deadlocks.

I agree that we can already cause deadlocks now and especially with other primitives - I just wanted to point out that this opens up this particular likely pitfall.

mhuisi avatar Mar 11 '24 12:03 mhuisi