master
Drew Owens Share frozen native Rust mechanical development checkpoint and qualification scope b2d7cdb 26d ago
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169
//! Bounded, in-process handoff from workers to Fusion's main thread.
//!
//! The native event is only a wake-up containing [`Epoch`]. Tasks and results
//! remain in Rust; neither event data nor this crate contains SDK handles.
//! This queue is not a durable journal or permission to mutate a document.
//! A timed-out running request is unknown, never retried or requeued.

use std::collections::{BTreeMap, VecDeque};
use std::fmt;
use std::io;
use std::marker::PhantomData;
use std::rc::Rc;
use std::str::FromStr;
use std::sync::{Arc, Condvar, Mutex, MutexGuard};
use std::thread::{self, ThreadId};
use std::time::Instant;

/// A random runtime identity, independent of IDs from any previous DLL load.
/// Epochs prevent stale wakes; they are not authentication credentials.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub struct Epoch([u8; 16]);

impl Epoch {
    fn fresh() -> io::Result<Self> {
        let mut bytes = [0; 16];
        random_bytes(&mut bytes)?;
        Ok(Self(bytes))
    }
}

impl fmt::Display for Epoch {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        for byte in self.0 {
            write!(f, "{byte:02x}")?;
        }
        Ok(())
    }
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct InvalidEpoch;

impl fmt::Display for InvalidEpoch {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str("an epoch must contain exactly 32 hexadecimal ASCII characters")
    }
}

impl std::error::Error for InvalidEpoch {}

impl FromStr for Epoch {
    type Err = InvalidEpoch;

    fn from_str(input: &str) -> Result<Self, Self::Err> {
        let raw = input.as_bytes();
        if raw.len() != 32 || !raw.iter().all(u8::is_ascii_hexdigit) {
            return Err(InvalidEpoch);
        }
        let mut bytes = [0; 16];
        for (i, output) in bytes.iter_mut().enumerate() {
            // ASCII validation above also establishes valid UTF-8 boundaries.
            *output = u8::from_str_radix(&input[i * 2..i * 2 + 2], 16).map_err(|_| InvalidEpoch)?;
        }
        Ok(Self(bytes))
    }
}

#[cfg(unix)]
fn random_bytes(bytes: &mut [u8; 16]) -> io::Result<()> {
    use std::io::Read;
    std::fs::File::open("/dev/urandom")?.read_exact(bytes)
}

#[cfg(windows)]
fn random_bytes(bytes: &mut [u8; 16]) -> io::Result<()> {
    #[link(name = "bcrypt")]
    extern "system" {
        fn BCryptGenRandom(
            algorithm: *mut std::ffi::c_void,
            buffer: *mut u8,
            len: u32,
            flags: u32,
        ) -> i32;
    }
    // BCRYPT_USE_SYSTEM_PREFERRED_RNG; NTSTATUS success is nonnegative.
    let status = unsafe { BCryptGenRandom(std::ptr::null_mut(), bytes.as_mut_ptr(), 16, 2) };
    if status < 0 {
        Err(io::Error::other(format!(
            "BCryptGenRandom failed: {status:#x}"
        )))
    } else {
        Ok(())
    }
}

#[cfg(not(any(unix, windows)))]
fn random_bytes(_bytes: &mut [u8; 16]) -> io::Result<()> {
    Err(io::Error::new(
        io::ErrorKind::Unsupported,
        "no supported OS random source",
    ))
}

#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub struct RequestId {
    epoch: Epoch,
    sequence: u64,
}

impl RequestId {
    pub fn epoch(self) -> Epoch {
        self.epoch
    }
    pub fn sequence(self) -> u64 {
        self.sequence
    }
}

impl fmt::Display for RequestId {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{}:{}", self.epoch, self.sequence)
    }
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SubmitError {
    Full,
    ShuttingDown,
    DeadlineElapsed,
    IdsExhausted,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum DrainError {
    StaleEpoch,
    WrongThread,
    ShuttingDown,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum CompleteError {
    ClaimMissing,
    ClaimNotExecuting,
}

macro_rules! debug_error {
    ($($name:ty),+ $(,)?) => {$ (
        impl fmt::Display for $name {
            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "{self:?}") }
        }
        impl std::error::Error for $name {}
    )+ };
}
debug_error!(SubmitError, DrainError, CompleteError);

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum NotExecutedReason {
    DeadlineElapsed,
    Cancelled,
    Shutdown,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum UnknownReason {
    DeadlineWhileExecuting,
    CancelledWhileExecuting,
    ShutdownWhileExecuting,
    ExecutionAbandoned,
}

#[derive(Debug, Eq, PartialEq)]
pub enum Outcome<R> {
    Completed(R),
    NotExecuted(NotExecutedReason),
    Unknown(UnknownReason),
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Status {
    Queued,
    Executing,
    Finished,
}

#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct ShutdownSummary {
    pub cancelled_queued: usize,
    pub executing: usize,
}

enum Phase<R> {
    Queued,
    Executing,
    Finished(Outcome<R>),
}

struct Entry<T, R> {
    task: Option<T>,
    deadline: Instant,
    phase: Phase<R>,
    receiver_alive: bool,
}

struct Inner<T, R> {
    entries: BTreeMap<u64, Entry<T, R>>,
    queue: VecDeque<u64>,
    next_sequence: u64,
    stopped: bool,
}

pub struct Runtime<T, R> {
    epoch: Epoch,
    main_thread: ThreadId,
    capacity: usize,
    inner: Mutex<Inner<T, R>>,
    changed: Condvar,
}

impl<T, R> Runtime<T, R> {
    /// Call on the thread that will own all native SDK access. Admission and
    /// observation may happen on workers; draining is confined to this thread.
    pub fn new(capacity: usize) -> io::Result<Arc<Self>> {
        if capacity == 0 {
            return Err(io::Error::new(
                io::ErrorKind::InvalidInput,
                "queue capacity must be positive",
            ));
        }
        Ok(Arc::new(Self {
            epoch: Epoch::fresh()?,
            main_thread: thread::current().id(),
            capacity,
            inner: Mutex::new(Inner {
                entries: BTreeMap::new(),
                queue: VecDeque::new(),
                next_sequence: 1,
                stopped: false,
            }),
            changed: Condvar::new(),
        }))
    }

    // A poison event never makes work runnable again. There is no user callback
    // under this lock; recovery preserves the monotonic phase transitions.
    fn lock(&self) -> MutexGuard<'_, Inner<T, R>> {
        self.inner.lock().unwrap_or_else(|e| e.into_inner())
    }

    pub fn epoch(&self) -> Epoch {
        self.epoch
    }

    /// Includes unobserved completions and detached running work, so memory and
    /// outstanding execution remain bounded even if clients stop reading.
    pub fn outstanding(&self) -> usize {
        self.lock().entries.len()
    }

    pub fn is_shutdown(&self) -> bool {
        self.lock().stopped
    }

    /// Read-only wake decision. Completed/unobserved results and executing
    /// claims do not justify another callback. Never revives a stopped epoch.
    pub fn has_queued(&self) -> bool {
        let inner = self.lock();
        !inner.stopped
            && inner
                .entries
                .values()
                .any(|entry| matches!(entry.phase, Phase::Queued))
    }

    /// Earliest original deadline still awaiting a native claim. Expired queued
    /// entries remain visible until settled: a lost wake must not gain a later
    /// deadline merely because a newer request arrived.
    pub fn earliest_queued_deadline(&self) -> Option<Instant> {
        let inner = self.lock();
        if inner.stopped {
            return None;
        }
        inner
            .entries
            .values()
            .filter(|entry| matches!(entry.phase, Phase::Queued))
            .map(|entry| entry.deadline)
            .min()
    }

    pub fn status(&self, id: RequestId) -> Option<Status> {
        if id.epoch != self.epoch {
            return None;
        }
        self.lock()
            .entries
            .get(&id.sequence)
            .map(|entry| match entry.phase {
                Phase::Queued => Status::Queued,
                Phase::Executing => Status::Executing,
                Phase::Finished(_) => Status::Finished,
            })
    }

    pub fn submit(
        self: &Arc<Self>,
        task: T,
        deadline: Instant,
    ) -> Result<Pending<T, R>, SubmitError> {
        let mut inner = self.lock();
        if inner.stopped {
            return Err(SubmitError::ShuttingDown);
        }
        if deadline <= Instant::now() {
            return Err(SubmitError::DeadlineElapsed);
        }
        if inner.entries.len() >= self.capacity {
            return Err(SubmitError::Full);
        }
        // Refuse rather than wrap and accidentally alias any previous request.
        let sequence = inner.next_sequence;
        inner.next_sequence = sequence.checked_add(1).ok_or(SubmitError::IdsExhausted)?;
        inner.entries.insert(
            sequence,
            Entry {
                task: Some(task),
                deadline,
                phase: Phase::Queued,
                receiver_alive: true,
            },
        );
        inner.queue.push_back(sequence);
        Ok(Pending {
            runtime: Arc::clone(self),
            id: RequestId {
                epoch: self.epoch,
                sequence,
            },
            attached: true,
        })
    }

    /// Claim at most one task. Expired queued requests are settled as not
    /// executed. Extra or repeated native wake events cannot duplicate claims.
    pub fn take_next(self: &Arc<Self>, epoch: Epoch) -> Result<Option<Claim<T, R>>, DrainError> {
        if epoch != self.epoch {
            return Err(DrainError::StaleEpoch);
        }
        if thread::current().id() != self.main_thread {
            return Err(DrainError::WrongThread);
        }
        let mut inner = self.lock();
        if inner.stopped {
            return Err(DrainError::ShuttingDown);
        }
        let mut expired_tasks = Vec::new();
        while let Some(sequence) = inner.queue.pop_front() {
            let entry = inner
                .entries
                .get_mut(&sequence)
                .expect("queued entry exists");
            if entry.deadline <= Instant::now() {
                entry.phase =
                    Phase::Finished(Outcome::NotExecuted(NotExecutedReason::DeadlineElapsed));
                expired_tasks.push(entry.task.take());
                self.changed.notify_all();
                continue;
            }
            entry.phase = Phase::Executing;
            let task = entry.task.take().expect("queued entry owns task");
            let claim = Claim {
                runtime: Arc::clone(self),
                id: RequestId {
                    epoch: self.epoch,
                    sequence,
                },
                task,
                completed: false,
                main_thread_only: PhantomData,
            };
            drop(inner);
            drop(expired_tasks);
            return Ok(Some(claim));
        }
        drop(inner);
        drop(expired_tasks);
        Ok(None)
    }

    /// Stops admission and unstarted work, wakes observers immediately, and
    /// never revokes a running main-thread claim. Safe from any Rust thread.
    pub fn shutdown(&self, epoch: Epoch) -> Result<ShutdownSummary, DrainError> {
        if epoch != self.epoch {
            return Err(DrainError::StaleEpoch);
        }
        let mut inner = self.lock();
        inner.stopped = true;
        let queued: Vec<_> = inner.queue.drain(..).collect();
        let cancelled_queued = queued.len();
        let mut cancelled_tasks = Vec::new();
        for sequence in queued {
            let entry = inner
                .entries
                .get_mut(&sequence)
                .expect("queued entry exists");
            entry.phase = Phase::Finished(Outcome::NotExecuted(NotExecutedReason::Shutdown));
            cancelled_tasks.push(entry.task.take());
        }
        let executing = inner
            .entries
            .values()
            .filter(|e| matches!(e.phase, Phase::Executing))
            .count();
        self.changed.notify_all();
        drop(inner);
        drop(cancelled_tasks);
        Ok(ShutdownSummary {
            cancelled_queued,
            executing,
        })
    }

    fn finish(&self, id: RequestId, outcome: Outcome<R>) -> Result<(), CompleteError> {
        let mut inner = self.lock();
        let entry = inner
            .entries
            .get_mut(&id.sequence)
            .ok_or(CompleteError::ClaimMissing)?;
        if !matches!(entry.phase, Phase::Executing) {
            return Err(CompleteError::ClaimNotExecuting);
        }
        if entry.receiver_alive {
            entry.phase = Phase::Finished(outcome);
        } else {
            inner.entries.remove(&id.sequence);
        }
        self.changed.notify_all();
        Ok(())
    }
}

/// Unique observation handle. Dropping it cancels queued work but only detaches
/// from running work. It never duplicates, revokes, or retries native execution.
pub struct Pending<T, R> {
    runtime: Arc<Runtime<T, R>>,
    id: RequestId,
    attached: bool,
}

impl<T, R> Pending<T, R> {
    pub fn id(&self) -> RequestId {
        self.id
    }

    pub fn wait(self) -> Outcome<R> {
        self.wait_inner(false)
    }

    /// Owned execution coordinators must retain observation of claimed effects
    /// after the HTTP observer deadline or queue shutdown. Queued work still
    /// expires normally. A claimed task settles only on complete or Claim drop.
    /// The owner must arrange callback settlement before joining this waiter.
    pub fn wait_settled(self) -> Outcome<R> {
        self.wait_inner(true)
    }

    fn wait_inner(mut self, retain_executing: bool) -> Outcome<R> {
        let mut inner = self.runtime.lock();
        loop {
            let entry = inner
                .entries
                .get(&self.id.sequence)
                .expect("attached receiver has entry");
            if matches!(entry.phase, Phase::Finished(_)) {
                let entry = inner
                    .entries
                    .remove(&self.id.sequence)
                    .expect("finished entry exists");
                self.attached = false;
                if let Phase::Finished(outcome) = entry.phase {
                    return outcome;
                }
                unreachable!();
            }
            if retain_executing && matches!(entry.phase, Phase::Executing) {
                inner = self
                    .runtime
                    .changed
                    .wait(inner)
                    .unwrap_or_else(|e| e.into_inner());
                continue;
            }
            if inner.stopped {
                self.attached = false;
                let (outcome, task) = detach(
                    &mut inner,
                    self.id.sequence,
                    NotExecutedReason::Shutdown,
                    UnknownReason::ShutdownWhileExecuting,
                );
                drop(inner);
                drop(task);
                return outcome;
            }
            let now = Instant::now();
            if now >= entry.deadline {
                self.attached = false;
                let (outcome, task) = detach(
                    &mut inner,
                    self.id.sequence,
                    NotExecutedReason::DeadlineElapsed,
                    UnknownReason::DeadlineWhileExecuting,
                );
                drop(inner);
                drop(task);
                return outcome;
            }
            let duration = entry.deadline.saturating_duration_since(now);
            inner = self
                .runtime
                .changed
                .wait_timeout(inner, duration)
                .unwrap_or_else(|e| e.into_inner())
                .0;
        }
    }

    pub fn cancel(mut self) -> Outcome<R> {
        let mut inner = self.runtime.lock();
        self.attached = false;
        let (outcome, task) = detach(
            &mut inner,
            self.id.sequence,
            NotExecutedReason::Cancelled,
            UnknownReason::CancelledWhileExecuting,
        );
        drop(inner);
        drop(task);
        outcome
    }
}

fn detach<T, R>(
    inner: &mut Inner<T, R>,
    sequence: u64,
    queued_reason: NotExecutedReason,
    executing_reason: UnknownReason,
) -> (Outcome<R>, Option<T>) {
    let entry = inner
        .entries
        .get_mut(&sequence)
        .expect("attached receiver has entry");
    match entry.phase {
        Phase::Queued => {
            inner.queue.retain(|id| *id != sequence);
            let entry = inner
                .entries
                .remove(&sequence)
                .expect("queued entry exists");
            (Outcome::NotExecuted(queued_reason), entry.task)
        }
        Phase::Executing => {
            entry.receiver_alive = false;
            (Outcome::Unknown(executing_reason), None)
        }
        Phase::Finished(_) => {
            let entry = inner
                .entries
                .remove(&sequence)
                .expect("finished entry exists");
            if let Phase::Finished(outcome) = entry.phase {
                (outcome, None)
            } else {
                unreachable!()
            }
        }
    }
}

impl<T, R> Drop for Pending<T, R> {
    fn drop(&mut self) {
        if self.attached {
            let mut inner = self.runtime.lock();
            let detached = detach(
                &mut inner,
                self.id.sequence,
                NotExecutedReason::Cancelled,
                UnknownReason::CancelledWhileExecuting,
            );
            drop(inner);
            drop(detached);
        }
    }
}

/// A unique main-thread execution claim. This guard is deliberately `!Send` and
/// `!Sync`, and contains no SDK handle. Dropping it without completing settles
/// the observation as unknown; the task is never made runnable again.
///
/// Completing twice is rejected by ownership:
/// ```compile_fail
/// use fusion_native_dispatch::Runtime;
/// use std::time::{Instant, Duration};
/// let queue = Runtime::<(), ()>::new(1).unwrap();
/// let pending = queue.submit((), Instant::now() + Duration::from_secs(1)).unwrap();
/// let claim = queue.take_next(queue.epoch()).unwrap().unwrap();
/// claim.complete(()).unwrap();
/// claim.complete(()).unwrap();
/// ```
/// A claim cannot cross to a worker thread:
/// ```compile_fail
/// use fusion_native_dispatch::Runtime;
/// use std::time::{Instant, Duration};
/// let queue = Runtime::<(), ()>::new(1).unwrap();
/// let pending = queue.submit((), Instant::now() + Duration::from_secs(1)).unwrap();
/// let claim = queue.take_next(queue.epoch()).unwrap().unwrap();
/// std::thread::spawn(move || claim.complete(()));
/// ```
pub struct Claim<T, R> {
    runtime: Arc<Runtime<T, R>>,
    id: RequestId,
    task: T,
    completed: bool,
    main_thread_only: PhantomData<Rc<()>>,
}

impl<T, R> Claim<T, R> {
    pub fn id(&self) -> RequestId {
        self.id
    }
    pub fn task(&self) -> &T {
        &self.task
    }

    /// Move non-cloneable task data out through an Option without transferring
    /// this main-thread-only claim or any permission to complete it twice.
    pub fn task_mut(&mut self) -> &mut T {
        &mut self.task
    }

    pub fn complete(mut self, result: R) -> Result<(), CompleteError> {
        let result = self.runtime.finish(self.id, Outcome::Completed(result));
        self.completed = true;
        result
    }
}

impl<T, R> Drop for Claim<T, R> {
    fn drop(&mut self) {
        if !self.completed {
            let _ = self
                .runtime
                .finish(self.id, Outcome::Unknown(UnknownReason::ExecutionAbandoned));
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use std::collections::BTreeSet;
    #[test]
    fn owned_waiter_keeps_claimed_result_after_deadline_and_shutdown() {
        let runtime = Runtime::<(), u32>::new(1).unwrap();
        let pending = runtime
            .submit((), Instant::now() + Duration::from_millis(20))
            .unwrap();
        let claim = runtime.take_next(runtime.epoch()).unwrap().unwrap();
        let (sender, receiver) = std::sync::mpsc::channel();
        let waiter = std::thread::spawn(move || sender.send(pending.wait_settled()).unwrap());
        std::thread::sleep(Duration::from_millis(30));
        runtime.shutdown(runtime.epoch()).unwrap();
        assert!(receiver.recv_timeout(Duration::from_millis(20)).is_err());
        claim.complete(17).unwrap();
        assert_eq!(
            receiver.recv_timeout(Duration::from_secs(1)).unwrap(),
            Outcome::Completed(17)
        );
        waiter.join().unwrap();
        assert_eq!(runtime.outstanding(), 0);
    }
    #[test]
    fn owned_waiter_still_expires_unclaimed_work_and_observes_abandonment() {
        let runtime = Runtime::<(), u32>::new(1).unwrap();
        let pending = runtime
            .submit((), Instant::now() + Duration::from_millis(5))
            .unwrap();
        assert_eq!(
            pending.wait_settled(),
            Outcome::NotExecuted(NotExecutedReason::DeadlineElapsed)
        );
        let pending = runtime
            .submit((), Instant::now() + Duration::from_secs(1))
            .unwrap();
        let claim = runtime.take_next(runtime.epoch()).unwrap().unwrap();
        drop(claim);
        assert_eq!(
            pending.wait_settled(),
            Outcome::Unknown(UnknownReason::ExecutionAbandoned)
        );
    }
    use std::sync::{mpsc, Barrier, Weak};
    use std::time::Duration;

    fn future() -> Instant {
        Instant::now() + Duration::from_secs(30)
    }

    fn expire<T, R>(runtime: &Runtime<T, R>, id: RequestId) {
        runtime
            .lock()
            .entries
            .get_mut(&id.sequence)
            .unwrap()
            .deadline = Instant::now();
        runtime.changed.notify_all();
    }

    #[test]
    fn epochs_are_fresh_and_only_accept_exact_hex_wakes() {
        let a = Runtime::<(), ()>::new(1).unwrap();
        let b = Runtime::<(), ()>::new(1).unwrap();
        assert_ne!(a.epoch(), b.epoch());
        assert_eq!(a.epoch().to_string().parse::<Epoch>().unwrap(), a.epoch());
        for bad in [
            "",
            "a",
            "gggggggggggggggggggggggggggggggg",
            "00000000000000000000000000000000extra",
            "éééééééééééééééé",
        ] {
            assert_eq!(bad.parse::<Epoch>(), Err(InvalidEpoch));
        }
        assert!(matches!(
            a.take_next(b.epoch()),
            Err(DrainError::StaleEpoch)
        ));
        assert_eq!(a.shutdown(b.epoch()), Err(DrainError::StaleEpoch));
        assert!(!a.is_shutdown());
    }

    #[test]
    fn empty_and_repeated_wakes_never_duplicate_claims() {
        let runtime = Runtime::new(2).unwrap();
        assert!(runtime.take_next(runtime.epoch()).unwrap().is_none());
        let pending = runtime.submit("snapshot", future()).unwrap();
        let id = pending.id();
        let claim = runtime.take_next(runtime.epoch()).unwrap().unwrap();
        assert_eq!(claim.id(), id);
        assert_eq!(*claim.task(), "snapshot");
        assert_eq!(runtime.status(id), Some(Status::Executing));
        for _ in 0..10 {
            assert!(runtime.take_next(runtime.epoch()).unwrap().is_none());
        }
        claim.complete("result").unwrap();
        assert_eq!(runtime.status(id), Some(Status::Finished));
        assert_eq!(pending.wait(), Outcome::Completed("result"));
        assert_eq!(runtime.status(id), None);
        assert_eq!(runtime.outstanding(), 0);
    }

    #[test]
    fn worker_thread_cannot_take_sdk_claim() {
        let runtime = Runtime::<(), ()>::new(1).unwrap();
        let pending = runtime.submit((), future()).unwrap();
        let worker = Arc::clone(&runtime);
        let error = thread::spawn(move || worker.take_next(worker.epoch()).err())
            .join()
            .unwrap();
        assert_eq!(error, Some(DrainError::WrongThread));
        assert_eq!(runtime.status(pending.id()), Some(Status::Queued));
    }

    #[test]
    fn capacity_includes_unread_completion_and_no_wrapped_request_ids() {
        assert!(Runtime::<(), ()>::new(0).is_err());
        let runtime = Runtime::new(1).unwrap();
        let pending = runtime.submit(1, future()).unwrap();
        let first_id = pending.id();
        assert!(matches!(
            runtime.submit(2, future()),
            Err(SubmitError::Full)
        ));
        runtime
            .take_next(runtime.epoch())
            .unwrap()
            .unwrap()
            .complete(7)
            .unwrap();
        assert!(matches!(
            runtime.submit(3, future()),
            Err(SubmitError::Full)
        ));
        assert_eq!(pending.wait(), Outcome::Completed(7));
        let next = runtime.submit(4, future()).unwrap();
        assert_eq!(next.id().sequence(), first_id.sequence() + 1);
        drop(next);
        runtime.lock().next_sequence = u64::MAX;
        for _ in 0..2 {
            assert!(matches!(
                runtime.submit(5, future()),
                Err(SubmitError::IdsExhausted)
            ));
        }
        assert_eq!(runtime.outstanding(), 0);
    }

    #[test]
    fn deadline_before_admission_has_no_id_or_queued_effect() {
        let runtime = Runtime::<(), ()>::new(1).unwrap();
        assert!(matches!(
            runtime.submit((), Instant::now()),
            Err(SubmitError::DeadlineElapsed)
        ));
        assert_eq!(runtime.outstanding(), 0);
        assert_eq!(runtime.submit((), future()).unwrap().id().sequence(), 1);
    }

    #[test]
    fn expired_queued_task_cannot_execute_from_a_late_wake() {
        let runtime = Runtime::<(), ()>::new(2).unwrap();
        let expired = runtime.submit((), future()).unwrap();
        expire(&runtime, expired.id());
        let next = runtime.submit((), future()).unwrap();
        let claim = runtime.take_next(runtime.epoch()).unwrap().unwrap();
        assert_eq!(claim.id(), next.id());
        assert_eq!(
            expired.wait(),
            Outcome::NotExecuted(NotExecutedReason::DeadlineElapsed)
        );
        claim.complete(()).unwrap();
        assert_eq!(next.wait(), Outcome::Completed(()));
    }

    #[test]
    fn queued_wait_timeout_and_cancellation_release_queue_and_capacity() {
        let runtime = Runtime::<(), ()>::new(1).unwrap();
        let pending = runtime.submit((), future()).unwrap();
        expire(&runtime, pending.id());
        assert_eq!(
            pending.wait(),
            Outcome::NotExecuted(NotExecutedReason::DeadlineElapsed)
        );
        assert!(runtime.take_next(runtime.epoch()).unwrap().is_none());
        let pending = runtime.submit((), future()).unwrap();
        assert_eq!(
            pending.cancel(),
            Outcome::NotExecuted(NotExecutedReason::Cancelled)
        );
        assert!(runtime.take_next(runtime.epoch()).unwrap().is_none());
        assert_eq!(runtime.outstanding(), 0);
        assert_eq!(runtime.lock().queue.len(), 0);
    }

    #[test]
    fn executing_timeout_is_unknown_and_retains_capacity_until_completion() {
        let runtime = Runtime::new(1).unwrap();
        let pending = runtime.submit((), future()).unwrap();
        let id = pending.id();
        let claim = runtime.take_next(runtime.epoch()).unwrap().unwrap();
        expire(&runtime, id);
        assert_eq!(
            pending.wait(),
            Outcome::Unknown(UnknownReason::DeadlineWhileExecuting)
        );
        assert_eq!(runtime.status(id), Some(Status::Executing));
        assert!(matches!(
            runtime.submit((), future()),
            Err(SubmitError::Full)
        ));
        assert!(runtime.take_next(runtime.epoch()).unwrap().is_none());
        claim.complete("late known result").unwrap();
        assert_eq!(runtime.status(id), None);
        assert_eq!(runtime.outstanding(), 0);
        assert!(runtime.submit((), future()).is_ok());
    }

    #[test]
    fn published_completion_wins_over_late_observer_deadline_or_cancel() {
        let runtime = Runtime::new(1).unwrap();
        let pending = runtime.submit((), future()).unwrap();
        let id = pending.id();
        runtime
            .take_next(runtime.epoch())
            .unwrap()
            .unwrap()
            .complete(42)
            .unwrap();
        expire(&runtime, id);
        assert_eq!(pending.wait(), Outcome::Completed(42));
        let pending = runtime.submit((), future()).unwrap();
        runtime
            .take_next(runtime.epoch())
            .unwrap()
            .unwrap()
            .complete(43)
            .unwrap();
        assert_eq!(pending.cancel(), Outcome::Completed(43));
    }

    #[test]
    fn abandoned_claim_is_unknown_and_never_requeued() {
        let runtime = Runtime::<(), ()>::new(1).unwrap();
        let pending = runtime.submit((), future()).unwrap();
        drop(runtime.take_next(runtime.epoch()).unwrap().unwrap());
        assert!(runtime.take_next(runtime.epoch()).unwrap().is_none());
        assert_eq!(
            pending.wait(),
            Outcome::Unknown(UnknownReason::ExecutionAbandoned)
        );
        assert_eq!(runtime.outstanding(), 0);
    }

    #[test]
    fn dropped_receiver_cancels_queued_and_detaches_executing_work() {
        let runtime = Runtime::<(), ()>::new(1).unwrap();
        for _ in 0..100 {
            drop(runtime.submit((), future()).unwrap());
        }
        assert_eq!(runtime.outstanding(), 0);
        assert!(runtime.lock().queue.is_empty());
        let pending = runtime.submit((), future()).unwrap();
        let claim = runtime.take_next(runtime.epoch()).unwrap().unwrap();
        drop(pending);
        assert_eq!(runtime.outstanding(), 1);
        drop(claim);
        assert_eq!(runtime.outstanding(), 0);
    }

    #[test]
    fn shutdown_wakes_waiters_immediately_without_stealing_running_claim() {
        let runtime = Runtime::<(), ()>::new(2).unwrap();
        let running = runtime.submit((), future()).unwrap();
        let claim = runtime.take_next(runtime.epoch()).unwrap().unwrap();
        let queued = runtime.submit((), future()).unwrap();
        let (tx, rx) = mpsc::channel();
        let tx2 = tx.clone();
        let running_waiter = thread::spawn(move || tx.send(running.wait()).unwrap());
        let queued_waiter = thread::spawn(move || tx2.send(queued.wait()).unwrap());
        assert_eq!(
            runtime.shutdown(runtime.epoch()).unwrap(),
            ShutdownSummary {
                cancelled_queued: 1,
                executing: 1
            }
        );
        let outcomes = [
            rx.recv_timeout(Duration::from_secs(2)).unwrap(),
            rx.recv_timeout(Duration::from_secs(2)).unwrap(),
        ];
        assert!(outcomes.contains(&Outcome::NotExecuted(NotExecutedReason::Shutdown)));
        assert!(outcomes.contains(&Outcome::Unknown(UnknownReason::ShutdownWhileExecuting)));
        assert_eq!(runtime.outstanding(), 1);
        assert!(matches!(
            runtime.take_next(runtime.epoch()),
            Err(DrainError::ShuttingDown)
        ));
        assert!(matches!(
            runtime.submit((), future()),
            Err(SubmitError::ShuttingDown)
        ));
        claim.complete(()).unwrap();
        assert_eq!(runtime.outstanding(), 0);
        assert_eq!(
            runtime.shutdown(runtime.epoch()).unwrap(),
            ShutdownSummary {
                cancelled_queued: 0,
                executing: 0
            }
        );
        running_waiter.join().unwrap();
        queued_waiter.join().unwrap();
    }

    #[test]
    fn condvar_deadline_and_completion_wake_real_waiters() {
        let runtime = Runtime::<(), u32>::new(1).unwrap();
        let pending = runtime
            .submit((), Instant::now() + Duration::from_secs(1))
            .unwrap();
        let (tx, rx) = mpsc::channel();
        let waiter = thread::spawn(move || tx.send(pending.wait()).unwrap());
        assert_eq!(
            rx.recv_timeout(Duration::from_secs(2)).unwrap(),
            Outcome::NotExecuted(NotExecutedReason::DeadlineElapsed)
        );
        waiter.join().unwrap();
        assert!(runtime.take_next(runtime.epoch()).unwrap().is_none());
        let pending = runtime.submit((), future()).unwrap();
        let claim = runtime.take_next(runtime.epoch()).unwrap().unwrap();
        let (tx, rx) = mpsc::channel();
        let waiter = thread::spawn(move || tx.send(pending.wait()).unwrap());
        claim.complete(123).unwrap();
        assert_eq!(
            rx.recv_timeout(Duration::from_secs(2)).unwrap(),
            Outcome::Completed(123)
        );
        waiter.join().unwrap();
        assert_eq!(runtime.outstanding(), 0);
    }

    #[test]
    fn shutdown_admission_race_either_refuses_or_settles_not_executed() {
        let runtime = Runtime::<(), ()>::new(16).unwrap();
        let barrier = Arc::new(Barrier::new(17));
        let mut workers = Vec::new();
        for _ in 0..16 {
            let barrier = Arc::clone(&barrier);
            let runtime = Arc::clone(&runtime);
            workers.push(thread::spawn(move || {
                barrier.wait();
                match runtime.submit((), future()) {
                    Ok(pending) => Some(pending.wait()),
                    Err(error) => {
                        assert_eq!(error, SubmitError::ShuttingDown);
                        None
                    }
                }
            }));
        }
        barrier.wait();
        runtime.shutdown(runtime.epoch()).unwrap();
        for worker in workers {
            if let Some(outcome) = worker.join().unwrap() {
                assert_eq!(outcome, Outcome::NotExecuted(NotExecutedReason::Shutdown));
            }
        }
        assert_eq!(runtime.outstanding(), 0);
        assert!(matches!(
            runtime.submit((), future()),
            Err(SubmitError::ShuttingDown)
        ));
    }

    #[test]
    fn cancellation_race_has_exactly_one_owner_and_never_retries() {
        let runtime = Runtime::<(), ()>::new(1).unwrap();
        for _ in 0..128 {
            let pending = runtime.submit((), future()).unwrap();
            let barrier = Arc::new(Barrier::new(2));
            let worker_barrier = Arc::clone(&barrier);
            let worker = thread::spawn(move || {
                worker_barrier.wait();
                pending.cancel()
            });
            barrier.wait();
            let claim = runtime.take_next(runtime.epoch()).unwrap();
            let outcome = worker.join().unwrap();
            match claim {
                None => assert_eq!(outcome, Outcome::NotExecuted(NotExecutedReason::Cancelled)),
                Some(claim) => {
                    assert_eq!(
                        outcome,
                        Outcome::Unknown(UnknownReason::CancelledWhileExecuting)
                    );
                    assert_eq!(runtime.outstanding(), 1);
                    claim.complete(()).unwrap();
                }
            }
            assert!(runtime.take_next(runtime.epoch()).unwrap().is_none());
            assert_eq!(runtime.outstanding(), 0);
        }
    }

    #[test]
    fn concurrent_admission_produces_unique_ids_and_fifo_claims() {
        let runtime = Runtime::<usize, usize>::new(128).unwrap();
        let (tx, rx) = mpsc::channel();
        let mut workers = Vec::new();
        for worker_id in 0..16 {
            let runtime = Arc::clone(&runtime);
            let tx = tx.clone();
            workers.push(thread::spawn(move || {
                for item in 0..8 {
                    tx.send(runtime.submit(worker_id * 8 + item, future()).unwrap())
                        .unwrap();
                }
            }));
        }
        drop(tx);
        let pending: Vec<_> = rx.into_iter().collect();
        for worker in workers {
            worker.join().unwrap();
        }
        assert_eq!(pending.len(), 128);
        let ids: BTreeSet<_> = pending.iter().map(|p| p.id().sequence()).collect();
        assert_eq!(ids, (1..=128).collect());
        let mut tasks = BTreeSet::new();
        for sequence in 1..=128 {
            let claim = runtime.take_next(runtime.epoch()).unwrap().unwrap();
            assert_eq!(claim.id().sequence(), sequence);
            let task = *claim.task();
            assert!(tasks.insert(task));
            claim.complete(task).unwrap();
        }
        for pending in pending {
            assert!(matches!(pending.wait(), Outcome::Completed(_)));
        }
        assert_eq!(tasks, (0..128).collect());
        assert_eq!(runtime.outstanding(), 0);
    }

    #[test]
    fn task_destructors_run_outside_internal_mutex() {
        struct ReentrantTask {
            runtime: Weak<Runtime<ReentrantTask, ()>>,
        }
        impl Drop for ReentrantTask {
            fn drop(&mut self) {
                if let Some(runtime) = self.runtime.upgrade() {
                    assert!(
                        runtime.inner.try_lock().is_ok(),
                        "task destructor held queue lock"
                    );
                }
            }
        }
        let runtime = Runtime::new(2).unwrap();
        let make = || ReentrantTask {
            runtime: Arc::downgrade(&runtime),
        };
        drop(runtime.submit(make(), future()).unwrap());
        let pending = runtime.submit(make(), future()).unwrap();
        pending.cancel();
        let pending = runtime.submit(make(), future()).unwrap();
        expire(&runtime, pending.id());
        pending.wait();
        let pending = runtime.submit(make(), future()).unwrap();
        expire(&runtime, pending.id());
        assert!(runtime.take_next(runtime.epoch()).unwrap().is_none());
        pending.wait();
        let pending = runtime.submit(make(), future()).unwrap();
        runtime.shutdown(runtime.epoch()).unwrap();
        pending.wait();
    }

    #[test]
    fn unread_and_detached_result_destructors_run_outside_mutex() {
        struct ReentrantResult {
            runtime: Weak<Runtime<(), ReentrantResult>>,
        }
        impl Drop for ReentrantResult {
            fn drop(&mut self) {
                if let Some(runtime) = self.runtime.upgrade() {
                    assert!(
                        runtime.inner.try_lock().is_ok(),
                        "result destructor held queue lock"
                    );
                }
            }
        }
        let runtime = Runtime::new(1).unwrap();
        let make = || ReentrantResult {
            runtime: Arc::downgrade(&runtime),
        };
        let pending = runtime.submit((), future()).unwrap();
        runtime
            .take_next(runtime.epoch())
            .unwrap()
            .unwrap()
            .complete(make())
            .unwrap();
        drop(pending);
        let pending = runtime.submit((), future()).unwrap();
        let claim = runtime.take_next(runtime.epoch()).unwrap().unwrap();
        drop(pending);
        claim.complete(make()).unwrap();
        assert_eq!(runtime.outstanding(), 0);
    }
}