Skip to main content

MandatoryThread

Struct MandatoryThread 

Source
pub struct MandatoryThread { /* private fields */ }
Expand description

A thread the IOC cannot correctly run without — the scan rates, the callback bands, the delayed-callback timer, the boot script.

§Invariant

An IOC that fails to start a mandatory thread MUST NOT continue serving. A thread-local panic is not that: on a panic = "unwind" target — and RTEMS and VxWorks both default to unwind — Builder::spawn(..).expect(..) kills only the thread that called it. Measured on a VxWorks 7 RTP on a 1 GB guest: EAGAIN from the periodic-scan spawn panicked the scan-owner thread, the stop guard it held unwound and stopped the rates that had started, and the process went on answering CA with zero periodic scanning — a half-IOC whose records simply never process.

C has no such state. spawnPeriodic (dbScan.c:943-959) calls epicsThreadCreateOpt and then epicsEventWait(startStopEvent); the event is posted by periodicTask itself, so when the thread was never created nobody posts it and iocInit wedges. C never reaches “serving”.

§Why there is no Result on spawn

Because there is nothing a caller could do with one that satisfies the invariant. Every caller that is not inside a fallible boot step would have to re-derive “this must be fatal” locally, and that is precisely the .expect the type exists to remove. The one shape that can satisfy it without aborting — a caller still inside a boot step that returns its error to the owner that decides whether to serve — is try_spawn, and that obligation is stated on it.

Name, band and stack class are constructor parameters for the same reason they are on spawn_dedicated_thread: a caller cannot omit what it must pass, so the RTEMS thread census (2 MiB default stacks, OS-anonymous threads) is closed by signature rather than by a source sweep.

Implementations§

Source§

impl MandatoryThread

Source

pub fn new( name: impl Into<String>, priority: ThreadPriority, stack: StackSizeClass, ) -> Self

Declare a mandatory thread: its C thread name, the EPICS band it holds, and the stack class the C IOC gives it.

Source

pub fn spawn<F>(self, f: F) -> JoinHandle<()>
where F: FnOnce() + Send + 'static,

Start it, or take the process down.

For every caller with no error path back to whoever decides that this IOC serves — a constructor returning Self, a OnceLock initialiser, a future that parks forever. See the type docs for why this returns no Result.

Source

pub fn try_spawn<F>(self, f: F) -> Result<JoinHandle<()>>
where F: FnOnce() + Send + 'static,

Start it, handing the failure to a caller that is still inside a fallible boot step.

The obligation this carries: the returned error MUST reach the owner that decides whether the IOC serves, and that owner MUST refuse. It must not be unwrapped, logged-and-ignored, or turned into a warning — any of those re-opens exactly the half-IOC the type docs describe. Use spawn when no such path exists.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more