Skip to main content

sequoia_async/
task.rs

1#![forbid(unsafe_code)]
2
3#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
4pub struct TaskId(u64);
5
6impl TaskId {
7    pub fn new(raw: u64) -> Self {
8        Self(raw)
9    }
10
11    pub fn get(self) -> u64 {
12        self.0
13    }
14}
15
16impl std::fmt::Display for TaskId {
17    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
18        write!(f, "task#{}", self.0)
19    }
20}
21
22#[derive(Clone, Copy, Debug, PartialEq, Eq)]
23#[non_exhaustive]
24pub enum JoinError {
25    Cancelled,
26
27    Panicked,
28}
29
30impl std::fmt::Display for JoinError {
31    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32        match self {
33            Self::Cancelled => write!(f, "task was cancelled"),
34            Self::Panicked => write!(f, "task panicked on worker"),
35        }
36    }
37}
38
39impl std::error::Error for JoinError {}
40
41#[derive(Clone)]
42pub struct TaskHandle {
43    id: TaskId,
44    cancel: std::rc::Rc<dyn Fn(TaskId) -> bool>,
45}
46
47impl TaskHandle {
48    pub fn new(id: TaskId, cancel: impl Fn(TaskId) -> bool + 'static) -> Self {
49        Self {
50            id,
51            cancel: std::rc::Rc::new(cancel),
52        }
53    }
54
55    pub fn id(&self) -> TaskId {
56        self.id
57    }
58
59    pub fn cancel(&self) -> bool {
60        (self.cancel)(self.id)
61    }
62}
63
64impl std::fmt::Debug for TaskHandle {
65    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
66        f.debug_struct("TaskHandle").field("id", &self.id).finish()
67    }
68}
69
70#[cfg(test)]
71mod tests {
72    use super::*;
73
74    #[test]
75    fn handle_delegates_cancel_to_closure() {
76        let seen = std::rc::Rc::new(std::cell::RefCell::new(Vec::new()));
77        let probe = std::rc::Rc::clone(&seen);
78        let h = TaskHandle::new(TaskId::new(7), move |id| {
79            probe.borrow_mut().push(id.get());
80            true
81        });
82        assert_eq!(h.id().get(), 7);
83        assert!(h.cancel());
84        assert_eq!(*seen.borrow(), vec![7]);
85    }
86
87    #[test]
88    fn task_id_orders_and_displays() {
89        assert!(TaskId::new(1) < TaskId::new(2));
90        assert_eq!(format!("{}", TaskId::new(3)), "task#3");
91    }
92}