cli_status_board/
task_id.rs

1use std::{
2    fmt::Display,
3    sync::{
4        Arc,
5        atomic::{AtomicI32, Ordering},
6        mpsc::Sender,
7    },
8};
9
10use crate::{Status, state::TaskEvent};
11
12static LATEST_ID: AtomicI32 = AtomicI32::new(0);
13
14#[derive(Debug, Clone)]
15pub struct TaskId {
16    id: i32,
17    maybe_sender: Option<Arc<Sender<TaskEvent>>>,
18}
19
20impl TaskId {
21    pub(crate) fn new() -> Self {
22        let id = LATEST_ID.fetch_add(1, Ordering::SeqCst) + 1;
23        Self {
24            id,
25            maybe_sender: None,
26        }
27    }
28
29    pub(crate) fn new_with_sender(sender: Sender<TaskEvent>) -> Self {
30        let id = LATEST_ID.fetch_add(1, Ordering::SeqCst) + 1;
31        Self {
32            id,
33            maybe_sender: Some(Arc::new(sender)),
34        }
35    }
36
37    pub(crate) fn make_weak(&self) -> TaskId {
38        Self {
39            id: self.id,
40            maybe_sender: None,
41        }
42    }
43}
44
45impl Eq for TaskId {}
46impl PartialEq for TaskId {
47    fn eq(&self, other: &Self) -> bool {
48        self.id == other.id
49    }
50}
51
52impl Display for TaskId {
53    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
54        write!(f, "{}", self.id)
55    }
56}
57
58impl Drop for TaskId {
59    fn drop(&mut self) {
60        if let Some(sender_rc) = self.maybe_sender.take() {
61            // This is about to drop, so let's go ahead and mark this task as "finished".
62            if let Some(sender) = Arc::into_inner(sender_rc) {
63                sender
64                    // Don't pass the sender in order to avoid infinite loops
65                    .send(TaskEvent::UpdateTask(self.make_weak(), Status::Finished))
66                    .unwrap();
67            }
68        }
69    }
70}