Skip to main content

running_process_platform_internal/
spawn_admission.rs

1//! Caller-owned exclusion at the native spawn boundary.
2
3use std::{any::Any, fmt, io, sync::Arc};
4
5/// Admission callback shared by cloned spawn descriptions.
6///
7/// Its permit covers only native process creation and is dropped before the
8/// caller can observe the child. The permit may be non-`Send`.
9#[derive(Clone)]
10pub struct SpawnAdmission {
11    acquire: Arc<dyn Fn() -> io::Result<Box<dyn Any>> + Send + Sync>,
12}
13
14impl fmt::Debug for SpawnAdmission {
15    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
16        formatter.write_str("SpawnAdmission { .. }")
17    }
18}
19
20impl SpawnAdmission {
21    /// Capture an admission function. Its returned permit is always dropped
22    /// after the native spawn attempt, including when that attempt fails.
23    pub fn new<F, G>(acquire: F) -> Self
24    where
25        F: Fn() -> io::Result<G> + Send + Sync + 'static,
26        G: 'static,
27    {
28        Self {
29            acquire: Arc::new(move || acquire().map(|permit| Box::new(permit) as Box<dyn Any>)),
30        }
31    }
32
33    pub(crate) fn run<T>(&self, spawn: impl FnOnce() -> io::Result<T>) -> io::Result<T> {
34        let _permit = (self.acquire)()?;
35        spawn()
36    }
37}