diff options
Diffstat (limited to 'src/processes.rs')
| -rw-r--r-- | src/processes.rs | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/src/processes.rs b/src/processes.rs new file mode 100644 index 0000000..7ac326f --- /dev/null +++ b/src/processes.rs @@ -0,0 +1,78 @@ +use std::collections::HashMap; +use std::sync::{LazyLock, RwLock, mpsc}; +use std::thread::JoinHandle; + +use happylock::ThreadKey; +use uuid::Uuid; + +use crate::pipe::{Message, MessageResponse}; + +thread_local! { + static PROCESS_ID: RwLock<Uuid> = const { RwLock::new(Uuid::nil()) }; +} + +static RUNNING_PROCESSES: LazyLock<RwLock<HashMap<Uuid, Process>>> = + LazyLock::new(|| RwLock::new(HashMap::new())); + +#[derive(Debug)] +pub struct Process { + id: Uuid, + thread: JoinHandle<()>, + channel: mpsc::Sender<Message>, +} + +pub fn is_builtin(program_id: Uuid) -> bool { + program_id.as_u64_pair().0 == 0 +} + +pub fn process_id(key: &mut ThreadKey) -> Uuid { + PROCESS_ID.with(|id| *id.read().unwrap()) +} + +pub fn send_message(key: &mut ThreadKey, program_id: Uuid, message: Message) -> MessageResponse { + start_program(key, program_id); + + let programs = RUNNING_PROCESSES.read().unwrap(); + // TODO: this can crash if the program runs and exits immediately + let program = programs.get(&program_id).unwrap(); + + let response = MessageResponse::from_message(&message); + _ = program.channel.send(message); + response +} + +pub fn start_builtin_as(key: &mut ThreadKey, package_id: Uuid, as_program: Uuid) -> Option<()> { + let mut processes = RUNNING_PROCESSES.write().unwrap(); + if processes.contains_key(&as_program) { + return Some(()); + } + + let builtin_index = package_id.as_u64_pair().1 as usize; + let func = crate::builtins::BUILTINS.get(builtin_index)?.as_ref()?; + let (sender, receiver) = mpsc::channel(); + let handle = std::thread::spawn(move || { + let key = ThreadKey::get().expect("the thread just started"); + PROCESS_ID.with(|id| { + *id.write().unwrap() = as_program; + }); + func(key, receiver); + }); + let process = Process { + id: as_program, + thread: handle, + channel: sender, + }; + processes.insert(as_program, process); + + Some(()) +} + +pub fn start_builtin(key: &mut ThreadKey, package_id: Uuid) -> Option<()> { + start_builtin_as(key, package_id, package_id) +} + +pub fn start_program(key: &mut ThreadKey, package_id: Uuid) -> Option<()> { + start_builtin(key, package_id)?; + + Some(()) +} |
