lean4-htt/tests/elab/cancel_token.lean
Joachim Breitner b763ab8a5e
refactor: keep IO.CancelToken task private, resolve promise before setting flag (#13569)
This PR addresses two review points on `IO.CancelToken`:

* `set` now resolves the underlying promise *before* writing the `Bool`
  fast-path flag, so observing `isSet = true` implies any synchronously
chained `onSet` callback has already run. The previous order (flag
first,
then resolve) was a subtle footgun: code seeing `isSet = true` could not
  rely on the cancellation task having fired.
* The underlying promise and the task it produces are kept private. The
prior `task : Task (Option Unit)` accessor is removed; consumers should
use `onSet` to react to cancellation. A comment on the structure records
  that re-exposing the task in the future requires re-auditing the order
  in `set` for races between the promise and the `Bool` flag.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-29 11:12:54 +00:00

42 lines
1.1 KiB
Text

/-! Tests for `IO.CancelToken.onSet`. -/
/-- `onSet` registered before `set` fires synchronously when `set` is called. -/
def testOnSetBeforeSet : IO Unit := do
let tk ← IO.CancelToken.new
let cell ← IO.mkRef false
tk.onSet (cell.set true)
if (← cell.get) then panic! "onSet fired too early"
tk.set
if !(← cell.get) then panic! "onSet did not fire"
IO.println "ok"
/-- `onSet` registered after `set` fires immediately at registration time. -/
def testOnSetAfterSet : IO Unit := do
let tk ← IO.CancelToken.new
tk.set
let cell ← IO.mkRef false
tk.onSet (cell.set true)
if !(← cell.get) then panic! "onSet did not fire on already-set token"
IO.println "ok"
/-- Multiple `onSet` callbacks all fire. -/
def testOnSetMultiple : IO Unit := do
let tk ← IO.CancelToken.new
let counter ← IO.mkRef 0
for _ in [0:5] do
tk.onSet (counter.modify (· + 1))
tk.set
let n ← counter.get
if n != 5 then panic! s!"expected 5 callbacks, got {n}"
IO.println "ok"
/--
info: ok
ok
ok
-/
#guard_msgs in
#eval do
testOnSetBeforeSet
testOnSetAfterSet
testOnSetMultiple