1use mumu::{
8 parser::interpreter::Interpreter,
9 parser::types::{Value, FunctionValue},
10 parser::interpreter::apply_one_function_value,
11};
12use std::ffi::c_void;
13use std::{
14 sync::{
15 Arc,
16 Mutex,
17 mpsc::{channel, Receiver, Sender},
18 atomic::{AtomicUsize, Ordering},
19 },
20 collections::HashMap,
21};
22use lazy_static::lazy_static;
23use indexmap::IndexMap;
24use whoami;
25
26pub static ACTIVE_TASKS: AtomicUsize = AtomicUsize::new(0);
28
29#[cfg(unix)]
31fn get_uid() -> i32 {
32 use nix::unistd::getuid;
33 getuid().as_raw() as i32
34}
35#[cfg(not(unix))]
36fn get_uid() -> i32 {
37 0
38}
39
40#[allow(dead_code)]
42enum ProcessMessage {
43 Ok(usize, Value),
44 Err(usize, String),
45}
46
47struct ProcessTask {
48 callback: Box<FunctionValue>,
49 done: bool,
50}
51
52struct ProcessManager {
53 _next_id: usize,
55 tasks: HashMap<usize, ProcessTask>,
56 _tx: Sender<ProcessMessage>,
57 rx: Receiver<ProcessMessage>,
58 active_count: AtomicUsize,
59}
60
61impl ProcessManager {
62 fn new() -> Self {
63 let (tx, rx) = channel();
64 Self {
65 _next_id: 0,
66 tasks: HashMap::new(),
67 _tx: tx,
68 rx,
69 active_count: AtomicUsize::new(0),
70 }
71 }
72
73 fn poll_events(&mut self, interp: &mut Interpreter) {
74 while let Ok(msg) = self.rx.try_recv() {
75 match msg {
76 ProcessMessage::Ok(id, data_val) => {
77 if let Some(t) = self.tasks.get_mut(&id) {
78 if !t.done {
79 t.done = true;
80 let _ = apply_one_function_value(interp, t.callback.clone(), data_val);
81 }
82 }
83 }
84 ProcessMessage::Err(id, err_str) => {
85 if let Some(t) = self.tasks.get_mut(&id) {
86 if !t.done {
87 t.done = true;
88 let mut map = IndexMap::new();
89 map.insert("error".to_string(), Value::SingleString(err_str));
90 let final_val = Value::KeyedArray(map);
91 let _ = apply_one_function_value(interp, t.callback.clone(), final_val);
92 }
93 }
94 }
95 }
96 }
97
98 let before = self.tasks.len();
99 self.tasks.retain(|_, t| !t.done);
100 let removed = before.saturating_sub(self.tasks.len());
101 if removed > 0 {
102 self.active_count.fetch_sub(removed, Ordering::SeqCst);
103 }
104 }
105
106 fn count_tasks(&self) -> usize {
107 self.active_count.load(Ordering::SeqCst)
108 }
109}
110
111#[allow(dead_code)]
113fn process_spawn_bridge(
114 _interp: &mut Interpreter,
115 _args: Vec<Value>
116) -> Result<Value, String> {
117 Ok(Value::Bool(true))
119}
120
121fn process_info_bridge(
123 interp: &mut Interpreter,
124 mut args: Vec<Value>
125) -> Result<Value, String> {
126 if args.len() != 1 {
127 return Err(format!("process:info => expected 1 argument => callback, got {}", args.len()));
128 }
129 let callback_val = args.remove(0);
130 let callback_func = match callback_val {
131 Value::Function(fb) => fb,
132 other => return Err(format!("process:info => first arg must be function, got {:?}", other)),
133 };
134
135 let mut map = IndexMap::new();
137 let pid_u32 = std::process::id();
138 map.insert("pid".to_string(), Value::Int(pid_u32 as i32));
139 map.insert("uid".to_string(), Value::Int(get_uid()));
140 map.insert("username".to_string(), Value::SingleString(whoami::username()));
141 map.insert("binary_name".to_string(), Value::SingleString("mumu".into()));
142 map.insert("event_loop_len".to_string(), Value::Int(42));
143
144 let info_val = Value::KeyedArray(map);
145
146 let _ = apply_one_function_value(interp, callback_func, info_val)?;
148
149 Ok(Value::Bool(true))
150}
151
152fn process_check_tasks_bridge(
154 interp: &mut Interpreter,
155 _args: Vec<Value>
156) -> Result<Value, String> {
157 let mut mgr = PROCESS_MANAGER.lock().unwrap();
158 mgr.poll_events(interp);
159 let count = mgr.count_tasks();
160 Ok(Value::Int(count as i32))
161}
162
163lazy_static! {
164 static ref PROCESS_MANAGER: Mutex<ProcessManager> = Mutex::new(ProcessManager::new());
165}
166
167#[export_name = "Cargo_lock"]
168pub unsafe extern "C" fn cargo_lock(
169 interp_ptr: *mut c_void,
170 _extra_str: *const c_void,
171) -> i32 {
172 if interp_ptr.is_null() {
173 return 1;
174 }
175 let interp_ref = &mut *(interp_ptr as *mut Interpreter);
176
177 let info_fn = Arc::new(Mutex::new(process_info_bridge));
179 interp_ref.register_dynamic_function("process:info", info_fn);
180 interp_ref.set_variable(
181 "process:info",
182 Value::Function(Box::new(FunctionValue::Named("process:info".to_string())))
183 );
184
185 let check_fn = Arc::new(Mutex::new(process_check_tasks_bridge));
187 interp_ref.register_dynamic_function("process:check_tasks", check_fn);
188 interp_ref.set_variable(
189 "process:check_tasks",
190 Value::Function(Box::new(FunctionValue::Named("process:check_tasks".to_string())))
191 );
192
193 let poller = Arc::new(Mutex::new(move |interp: &mut Interpreter| {
203 let mut mgr = PROCESS_MANAGER.lock().unwrap();
204 mgr.poll_events(interp);
205 mgr.count_tasks()
206 }));
207 interp_ref.add_poller(poller);
208
209 0
210}