Skip to main content

transcribe_cpp/
cancel.rs

1//! Cooperative cancellation for in-flight runs and streams.
2//!
3//! A [`CancelToken`] wraps a shared atomic flag. Install it on a session, then
4//! call [`CancelToken::cancel`] from any thread to abort the in-flight
5//! `run`/`feed`/`finalize`: the native abort callback (polled between decode
6//! steps) sees the flag and stops, the call returns [`crate::Error::Aborted`]
7//! with the partial transcript, and [`crate::Session::was_aborted`] reports
8//! true.
9
10use std::os::raw::c_void;
11use std::sync::atomic::{AtomicBool, Ordering};
12use std::sync::Arc;
13
14/// A clonable cancellation handle. Clones share one underlying flag, so a
15/// worker thread can hold a clone and cancel a run executing on another thread.
16#[derive(Debug, Clone, Default)]
17pub struct CancelToken {
18    pub(crate) flag: Arc<AtomicBool>,
19}
20
21impl CancelToken {
22    /// A fresh, un-cancelled token.
23    pub fn new() -> Self {
24        CancelToken::default()
25    }
26
27    /// Request cancellation of the run/stream this token is installed on.
28    pub fn cancel(&self) {
29        self.flag.store(true, Ordering::SeqCst);
30    }
31
32    /// Whether cancellation has been requested.
33    pub fn is_cancelled(&self) -> bool {
34        self.flag.load(Ordering::SeqCst)
35    }
36
37    /// Clear the cancelled state so the token can be reused for another run.
38    pub fn reset(&self) {
39        self.flag.store(false, Ordering::SeqCst);
40    }
41}
42
43/// The C abort callback. `userdata` is an `Arc<AtomicBool>`'s pointee, kept
44/// alive by the session for the duration of any run. Invoked on the run thread
45/// (the C library polls it between decode steps), so it must be cheap and
46/// thread-safe — an atomic load is both.
47pub(crate) extern "C" fn abort_trampoline(userdata: *mut c_void) -> bool {
48    if userdata.is_null() {
49        return false;
50    }
51    // SAFETY: `userdata` is the `*const AtomicBool` the session installed and
52    // keeps alive (via a retained Arc) for as long as the callback is set.
53    let flag = unsafe { &*(userdata as *const AtomicBool) };
54    flag.load(Ordering::SeqCst)
55}