use std::ptr;
use std::sync::Mutex;
use tracing::error;
use llama_cpp_sys::{
ggml_numa_strategy, llama_backend_free, llama_backend_init, llama_log_set, llama_numa_init,
};
use crate::detail;
static BACKEND: Mutex<Option<(Backend, usize)>> = Mutex::new(None);
struct Backend {}
impl Backend {
fn init() -> Self {
unsafe {
llama_backend_init();
llama_numa_init(ggml_numa_strategy::GGML_NUMA_STRATEGY_DISTRIBUTE);
llama_log_set(Some(detail::llama_log_callback), ptr::null_mut());
}
Self {}
}
}
impl Drop for Backend {
fn drop(&mut self) {
unsafe {
llama_backend_free();
}
}
}
pub(crate) struct BackendRef {}
impl BackendRef {
pub(crate) fn new() -> Self {
let mut lock = BACKEND.lock().unwrap();
if let Some((_, count)) = lock.as_mut() {
*count += 1;
} else {
let _ = lock.insert((Backend::init(), 1));
}
Self {}
}
}
impl Drop for BackendRef {
fn drop(&mut self) {
let mut lock = BACKEND.lock().unwrap();
if let Some((_, count)) = lock.as_mut() {
*count -= 1;
if *count == 0 {
lock.take();
}
} else {
error!("Backend as already been freed, this should never happen")
}
}
}
impl Clone for BackendRef {
fn clone(&self) -> Self {
Self::new()
}
}