refactor(rwlock): move guard permits into access tokens - #351
Open
jeffoodchain wants to merge 1 commit into
Open
jeffoodchain wants to merge 1 commit into
jeffoodchain wants to merge 1 commit into
Conversation
tisonkun
self-requested a review
October 6, 2026 05:01
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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 20ManuallyDropwrappers and the 10 unsafeptr::readcalls that moved theArcout of owned guards; unsafe blocks underrwlock/drop from 36 to 26, and the newaccessmodule 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_mapthat 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, andusize::MAX, cancellation of a granted owned request,get_mutandinto_inner, and mapped guardSendbounds. 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 anOption, 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
CHANGELOGbug-fix entry, the sentence about wake-callback unwinding inLICENSE, and the panicking-waker regression test. The two macro-based projection tests are replaced by the scenario tests above.One measured cost of the
Optionowner (aarch64):Option<Guard>for the four unmapped guards grows by one word (for exampleOption<RwLockReadGuard<u64>>from 8 to 16 bytes), because the token uses up the pointer niche, and theirDerefgains aNonecheck. Storing the owner directly avoids both, at the price of oneArcclone per owned downgrade and amem::forgetin 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), andcargo x lint.