Skip to main content

kozan_platform/
view_thread.rs

1//! View thread types — handle and errors.
2//!
3//! The event loop and spawn logic live in `pipeline/`.
4
5use std::sync::mpsc;
6use std::thread;
7
8use kozan_scheduler::WakeSender;
9
10use crate::event::ViewEvent;
11
12/// Error returned when a thread fails to start.
13#[derive(Debug)]
14pub enum SpawnError {
15    ThreadSpawn(std::io::Error),
16    SetupFailed,
17}
18
19impl std::fmt::Display for SpawnError {
20    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
21        match self {
22            SpawnError::ThreadSpawn(e) => write!(f, "failed to spawn thread: {e}"),
23            SpawnError::SetupFailed => write!(f, "thread setup failed"),
24        }
25    }
26}
27
28impl std::error::Error for SpawnError {}
29
30/// Handle to a running view thread.
31pub struct ViewThreadHandle {
32    sender: mpsc::Sender<ViewEvent>,
33    wake_sender: WakeSender,
34    join_handle: Option<thread::JoinHandle<()>>,
35}
36
37impl ViewThreadHandle {
38    pub fn from_parts(
39        sender: mpsc::Sender<ViewEvent>,
40        wake_sender: WakeSender,
41        join_handle: thread::JoinHandle<()>,
42    ) -> Self {
43        Self {
44            sender,
45            wake_sender,
46            join_handle: Some(join_handle),
47        }
48    }
49
50    pub fn send(&self, event: ViewEvent) -> bool {
51        self.sender.send(event).is_ok()
52    }
53
54    pub fn wake_sender(&self) -> WakeSender {
55        self.wake_sender.clone()
56    }
57
58    pub fn shutdown(&mut self) {
59        let _ = self.sender.send(ViewEvent::Shutdown);
60        if let Some(h) = self.join_handle.take() {
61            let _ = h.join();
62        }
63    }
64}
65
66impl Drop for ViewThreadHandle {
67    fn drop(&mut self) {
68        self.shutdown();
69    }
70}