use mlx_native::encoder_worker::EncoderWorker;
use std::sync::{LazyLock, Mutex};
static GLOBAL_ENCODER_WORKER: LazyLock<Mutex<EncoderWorker>> =
LazyLock::new(|| Mutex::new(EncoderWorker::spawn()));
pub fn submit_to_global_worker<F>(f: F) -> Result<(), &'static str>
where
F: FnOnce() + Send + 'static,
{
let guard = GLOBAL_ENCODER_WORKER
.lock()
.map_err(|_| "global encoder worker mutex poisoned")?;
guard.submit(f)
}
#[cfg(test)]
mod tests {
use super::*;
use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::Arc;
#[test]
fn singleton_can_run_closure() {
let counter = Arc::new(AtomicU32::new(0));
let counter_clone = Arc::clone(&counter);
let (tx, rx) = std::sync::mpsc::channel();
submit_to_global_worker(move || {
counter_clone.fetch_add(1, Ordering::SeqCst);
tx.send(()).ok();
})
.expect("submit");
rx.recv().expect("worker did not signal");
assert_eq!(counter.load(Ordering::SeqCst), 1);
}
#[test]
fn singleton_persists_across_calls() {
let thread_ids = Arc::new(Mutex::new(Vec::new()));
let mut signals = Vec::new();
for _ in 0..3 {
let (tx, rx) = std::sync::mpsc::channel();
signals.push(rx);
let ids_clone = Arc::clone(&thread_ids);
submit_to_global_worker(move || {
let id = std::thread::current().id();
ids_clone.lock().expect("lock").push(id);
tx.send(()).ok();
})
.expect("submit");
}
for rx in signals {
rx.recv().expect("worker died");
}
let ids = thread_ids.lock().expect("lock");
assert_eq!(ids.len(), 3);
assert_eq!(ids[0], ids[1], "submissions ran on different threads");
assert_eq!(ids[1], ids[2], "submissions ran on different threads");
}
}