#[non_exhaustive]pub enum CpusetSpec {
Llc(usize),
Numa(usize),
Range {
start_frac: f64,
end_frac: f64,
},
Disjoint {
index: usize,
of: usize,
},
Overlap {
index: usize,
of: usize,
frac: f64,
},
Exact(BTreeSet<usize>),
}Expand description
How to compute a cpuset from topology.
§#[non_exhaustive]
CpusetSpec is #[non_exhaustive] — see
[crate::non_exhaustive] for the cross-crate pattern-match and
construction rules shared by every such type.
Variant-specific guidance for CpusetSpec: prefer the
associated constructor functions — Self::llc, Self::numa,
Self::range, Self::disjoint, Self::overlap, and
Self::exact — over naming variant literals like
CpusetSpec::Llc(0) or CpusetSpec::Range { start_frac, end_frac }. Two reasons:
- Stability across variant reshaping. A future commit that
adds a field to
Range(e.g. a stride parameter) breaks every caller that spelled outCpusetSpec::Range { start_frac, end_frac }; theSelf::range(..)constructor absorbs the new field behind a defaulted parameter. The#[non_exhaustive]attribute is what reserves that freedom for the enum; the constructor convention is how callers opt into benefiting from it. - Semantic consistency with
Self::exact. Theexactconstructor accepts anyIntoIterator<Item = usize>(arrays, ranges,Vec,BTreeSet) and converts toBTreeSet<usize>internally; callers that bypass it and writeCpusetSpec::Exact(set)directly must hand-build theBTreeSet— duplicate bookkeeping a future-proofed constructor erases.
Test code that needs to inspect a variant via pattern match necessarily references the variant literal (the name is load- bearing for the match), so the construction-side rule is a convention for production call sites, not a hard constraint. Inside this crate, matchers obey the pattern-side rule above; constructors obey this rule.
Clone + Debug + PartialEq. Eq / Hash are impossible
because Range and Overlap
carry f64 fractions; Default has no honest value (Llc(0)
vs. Range(0..1) vs. Exact(empty) are all different
“no-op” semantics).
Note: f64::NAN != f64::NAN per IEEE 754, so a CpusetSpec
containing NaN fractions will not equal a clone of itself;
validate() rejects NaN inputs.
Variants (Non-exhaustive)§
This enum is marked as non-exhaustive
Llc(usize)
All CPUs in a given LLC index.
Numa(usize)
All CPUs in a given NUMA node index.
Range
Fractional range of usable CPUs [start_frac..end_frac).
Disjoint
Partition usable CPUs into of equal disjoint sets; take the index-th.
Overlap
Like Disjoint but each set overlaps neighbors by frac of its size.
Exact(BTreeSet<usize>)
Exact CPU set (no topology resolution).
Implementations§
Source§impl CpusetSpec
impl CpusetSpec
Sourcepub fn exact(cpus: impl IntoIterator<Item = usize>) -> Self
pub fn exact(cpus: impl IntoIterator<Item = usize>) -> Self
Construct an Exact cpuset from any iterator of CPU indices.
Accepts arrays, ranges, Vec, BTreeSet, or any IntoIterator<Item = usize>.
Sourcepub const fn disjoint(index: usize, of: usize) -> Self
pub const fn disjoint(index: usize, of: usize) -> Self
Partition usable CPUs into of equal disjoint sets; take the index-th.
Sourcepub const fn overlap(index: usize, of: usize, frac: f64) -> Self
pub const fn overlap(index: usize, of: usize, frac: f64) -> Self
Like disjoint but each set overlaps neighbors by frac of its size.
Source§impl CpusetSpec
impl CpusetSpec
Sourcepub fn validate(&self, ctx: &Ctx<'_>) -> Result<(), String>
pub fn validate(&self, ctx: &Ctx<'_>) -> Result<(), String>
Check whether this spec can produce a non-empty cpuset for the
given topology. Returns Err with a human-readable reason on
failure.
Sourcepub fn resolve(&self, ctx: &Ctx<'_>) -> BTreeSet<usize>
pub fn resolve(&self, ctx: &Ctx<'_>) -> BTreeSet<usize>
Resolve to a concrete CPU set given the topology.
Callers SHOULD run Self::validate first and propagate
its error. apply_setup and apply_ops::SetCpuset do so
via anyhow::bail!, then call Self::resolve_quiet which
skips the warns this method emits on degenerate inputs.
Defense-in-depth: every malformed input that validate
rejects (out-of-range Llc/Numa, partition of == 0,
index >= of, inverted or non-finite Range.start_frac /
end_frac, out-of-bounds Overlap.frac) also has a
panic-free fallback here — out-of-range indices clamp to the
last valid index with a tracing::warn!, of == 0 returns
an empty set with a warn, and inverted/non-finite fracs
clamp to [0, len] so the resulting slice never inverts.
Skipping validate therefore degrades into a usable
(possibly empty) cpuset rather than crashing the caller, but
the warns surface the silent-degradation case — a caller who
computed a CPU count via crate::scenario::Ctx::cpuset_cpus
(which doesn’t validate) sees the warn instead of silently
planning against the wrong denominator.
Sourcepub fn resolve_quiet(&self, ctx: &Ctx<'_>) -> BTreeSet<usize>
pub fn resolve_quiet(&self, ctx: &Ctx<'_>) -> BTreeSet<usize>
Like Self::resolve but suppresses the degenerate-input
tracing::warn!s. Use this from call sites that pair the
resolution with a Self::validate call (either before or
after this one) and bail on its error — validate is the
canonical error channel for malformed specs, and a warn
here would be redundant noise on a path already known-
broken via the validate gate. apply_setup resolves first
(to keep the workers_pct empty-cpuset diagnostic ahead of
validate’s generic empty-Exact rejection) and validates
after; Op::SetCpuset validates first and resolves after.
Both patterns satisfy the contract.
Trait Implementations§
Source§impl Clone for CpusetSpec
impl Clone for CpusetSpec
Source§fn clone(&self) -> CpusetSpec
fn clone(&self) -> CpusetSpec
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for CpusetSpec
impl Debug for CpusetSpec
Source§impl PartialEq for CpusetSpec
impl PartialEq for CpusetSpec
impl StructuralPartialEq for CpusetSpec
Auto Trait Implementations§
impl Freeze for CpusetSpec
impl RefUnwindSafe for CpusetSpec
impl Send for CpusetSpec
impl Sync for CpusetSpec
impl Unpin for CpusetSpec
impl UnwindSafe for CpusetSpec
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more