feat(concurrency): poison-as-panic wrapper for std::sync#1540
Closed
daniel-noland wants to merge 1 commit into
Closed
Conversation
c712d12 to
8c6ea48
Compare
`std::sync::{Mutex, RwLock}` return `LockResult<Guard>` because they
poison on holder panic. Call sites that don't model recovery -- and
this workspace doesn't -- end up sprinkling `.unwrap()` /
`.expect("poisoned")` everywhere to satisfy the type system.
Replaces `pub use std::sync` with a thin module that wraps
`std::sync::{Mutex, RwLock}` in newtypes whose `lock()` /
`read()` / `write()` return naked guards. Poison is treated as a
fatal invariant violation and panics in a cold helper.
* The wrapper is `#[repr(transparent)]`-equivalent: it carries
`MutexGuard<'a, T>` / `RwLockReadGuard<'a, T>` etc. directly. The
hot path is one move; the cold-on-poison branch panics with a
uniform message.
* `Arc`, `Weak`, `atomic`, `mpsc`, `Once`, `OnceLock`, `Barrier`,
`Condvar` etc. are still re-exported from `std::sync` -- only the
poison-returning types are wrapped.
* `RwLock::upgradable_read` is implemented as exclusive `write()`
with a `parking_lot`-shaped `upgrade()` API. std has no native
upgradable read; subsequent backends (parking_lot) replace this
with a true upgradable read. The surface stays consistent.
* `T: Sized` on `RwLock` -- the lowest common denominator across the
backends that will land in subsequent PRs.
`concurrency/src/quiescent.rs` is the only in-tree caller that takes
a `Mutex`; its two `.expect("qsbr mutex poisoned")` call sites get
the naked guard directly under the default backend. Loom and shuttle
remain on their raw `LockResult`-based primitives at this point in
the stack; the call sites cfg-dispatch the `.expect` under those
backends until later PRs extend the wrapper to them.
`concurrency/src/slot.rs` doesn't need changes: its `Mutex<Arc<T>>`
fallback branch only fires under `loom`/`shuttle`/`_strict_provenance`,
where the wrapper isn't applied.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Signed-off-by: Daniel Noland <daniel@githedgehog.com>
7672b6e to
c87ff7f
Compare
8c6ea48 to
734ff09
Compare
Collaborator
Author
|
Folded into #1542 — the std-sync wrapper, parking_lot default, and consumer sweep can't be split without leaving the workspace uncompilable between them, so this stack collapses 2+3+4 into a single PR. |
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
concurrency::syncmodule exposingMutex/RwLockwith aparking_lot-shaped naked-guard surface backed by a poison-as-panic wrapper aroundstd::sync. Workspace policy treats a crashed thread as a crashed process: poison surfacing inside a lock acquire panics throughconcurrency::sync::poisoned()rather than handing back a possibly-tornLockResult.#[inline(never)] fn poisoned() -> !keeps the hot path branch-free; the wrapper is a singlematchper acquire, allSend/Sync/Default/From/Displayimpls forward to the wrapped type.RwLock::upgradable_readis implemented as exclusivewrite()for now; sound but lossy. Documented at the backend module level.Arc,Weak, atomics,Condvar,mpsc,OnceLock, etc. are re-exported fromstd::syncunchanged.concurrency::quiescentmigrates fromstd::sync::{Arc, Mutex}tocrate::sync::{Arc, Mutex}so the QSBR primitive consumes the facade.PR 2 of 6. Depends on #1539 — absorb-quiescent. The next PR layers
parking_lotas the default backend on top of this.