Skip to main content

Module state

Module state 

Source
Expand description

The composite: a thread’s ambient state, captured as one value.

AmbientState holds every aspect together, so a caller carries one value to a worker rather than remembering which pieces it collected. Its field list is contract surface: it is exhaustively enumerated, and a silently added field would be a silent semantic change.

§Capture fails on the calling thread, never later

Capture is synchronous and happens where the caller can still act on the result. A context that cannot be captured is an admission failure, not a deferred one – a worker discovering it later has no way to report it to anyone who can do anything about it, and by then the caller has usually moved on. The error names the aspect that failed, because “capture failed” is not actionable when three aspects could have caused it.

§Declared aspects are not captured

Declared values are supplied by the caller and read from nothing, so they are attached with AmbientState::with_declared rather than collected. That separation is why the capture set names only capturable aspects.

§One capture can serve many workers at once

AmbientState is both Send and Sync, so a single capture may be shared through an Arc and applied concurrently on any number of workers. That is the shape a traversal or scan engine actually has: capture once at submission, then run it on every worker for the length of the job. Each application installs and restores on its own thread and observes nothing of the others.

Sharing is also the cheap option. Capture duplicates a kernel token object, so re-capturing per unit of work re-pays for a snapshot the caller already holds.

§Granularity is the caller’s choice, and it costs something

Applying once around a batch of operations and applying once per operation are both expressible, and the crate deliberately does not choose. Each application is a SetThreadToken plus a call for every other aspect in play, so a worker that opens a thousand files pays that a thousand times if it applies per open.

Prefer the widest window the aspects allow – but note that the narrowest window is sometimes the correct one for a reason unrelated to cost: crates/windows-file-enumeration-sys deliberately impersonates only around its directory open, because every later query uses the resulting handle and needs no token at all. Holding a token longer than the work requires is a security decision, not just a performance one.

§The blast radius of fail-fast restoration

A failure to restore impersonation panics. That is inherited from windows_impersonation_token_sys rather than chosen here, and it is correct: a shared worker returned to a pool under an unknown identity is a process-wide security failure.

The consequence is worth stating plainly for anyone running many impersonated workers. A panic inside a thread-pool callback aborts the process – the pool has no caller to unwind to – so a restore failure on one worker of sixty-four is not one failed operation, it is the whole process. This is the intended trade, and a consumer that cannot accept it should not be applying impersonation on threads it does not own.

§Example

use windows_thread_ambient_sys::declared::MemoryPriority;
use windows_thread_ambient_sys::{AmbientState, CaptureSet, Declared};

// Collected from this thread, right now, where a failure is still ours.
let state = AmbientState::capture(CaptureSet::DEFAULT)?
    // Stated rather than read: nothing was collected for this.
    .with_declared(Declared::none().with_memory_priority(MemoryPriority::Low));

// What was asked for is recoverable afterwards, which is what keeps an
// omission distinguishable from an aspect that was captured and empty.
assert_eq!(state.captured_set(), CaptureSet::DEFAULT);
assert!(state.impersonation().was_captured());
assert!(!state.transaction().was_captured());

// Applying installs every aspect in a fixed order and releases in exact
// reverse. An uncaptured aspect is skipped, leaving the running thread's own
// value alone.
let applied = state.with_applied(|| "work")?;
assert_eq!(*applied.value(), "work");
assert!(applied.restore().is_clean());

Structs§

AmbientState
A thread’s ambient state, captured and declared, ready to travel.
Applied
What an operation produced, and whether the thread was put back.
ApplyError
Applying a composite state failed, so the operation did not run.
CaptureError
A composite capture failed.
RestoreReport
Which aspects could not be restored after an operation.

Enums§

ApplyFailure
Which aspect could not be installed, and why.
CaptureFailure
Which aspect failed to capture, and why.