Skip to content

refactor(rwlock): move guard permits into access tokens - #351

Open
jeffoodchain wants to merge 1 commit into
apache:mainfrom
jeffoodchain:refactor/rwlock-access-tokens
Open

jeffoodchain wants to merge 1 commit into
apache:mainfrom
jeffoodchain:refactor/rwlock-access-tokens

Conversation

@jeffoodchain

Copy link
Copy Markdown

Summary

Rework #289 on current main. RwLock's eight guard types now hold a private access token that owns their permits and releases them on drop, so projecting or downgrading a guard moves its token instead of suppressing the guard's destructor. This removes all 20 ManuallyDrop wrappers and the 10 unsafe ptr::read calls that moved the Arc out of owned guards; unsafe blocks under rwlock/ drop from 36 to 26, and the new access module has none. Public API signatures and auto traits are unchanged.

As in #289, apply ASF source headers to the nine rewritten files while keeping the Tokio copyright, MIT attribution, and pinned upstream links, update the RwLock paragraph in LICENSE, and remove the RwLock exemptions from the header checker. Replace the Tokio-derived documentation with the module-level guide and short item docs from #289; the three module examples replace the per-method examples.

Add tests for real events around projected guards: a rejected filter_map that hands the guard back, a cancelled reader or writer that holds a mapped guard while another request is queued, a projection that panics inside a spawned task, and an aborted task that owns a mapped guard. Together they use all eight guard types. Also keep #289's tests for downgrade at reader limits of 1, 3, and usize::MAX, cancellation of a granted owned request, get_mut and into_inner, and mapped guard Send bounds. All of these tests also pass against the previous implementation.

Design Notes

Tokens are the design from #289: a token stores its owner (a borrowed lock, a borrowed semaphore for borrowed projections, or an Arc) in an Option, and transfers take it. Downgrade creates the read token before it releases the other permits.

Three things from #289 are left out because the Waker Contract no longer supports recovery from panicking wakers: the CHANGELOG bug-fix entry, the sentence about wake-callback unwinding in LICENSE, and the panicking-waker regression test. The two macro-based projection tests are replaced by the scenario tests above.

One measured cost of the Option owner (aarch64): Option<Guard> for the four unmapped guards grows by one word (for example Option<RwLockReadGuard<u64>> from 8 to 16 bytes), because the token uses up the pointer niche, and their Deref gains a None check. Storing the owner directly avoids both, at the price of one Arc clone per owned downgrade and a mem::forget in the borrowed projection path. I kept #289's design here and can make that change in this PR or a follow-up.

Validation: cargo x test (593 passed), cargo x check (26 feature configurations), and cargo x lint.

@tisonkun
tisonkun self-requested a review October 6, 2026 05:01

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant