ik_llama_cpp_2/llama_backend.rs
1//! Process-wide ik_llama.cpp backend initialization.
2
3use std::sync::atomic::{AtomicBool, Ordering};
4
5use crate::LlamaError;
6
7static INITIALIZED: AtomicBool = AtomicBool::new(false);
8
9/// RAII proof that the ik_llama.cpp backend has been initialized.
10///
11/// Initialization is a process-wide singleton (like llama.cpp itself). Hold one
12/// `LlamaBackend` for the lifetime of your models/contexts; dropping it calls
13/// `llama_backend_free`.
14#[derive(Debug)]
15pub struct LlamaBackend {
16 _private: (),
17}
18
19impl LlamaBackend {
20 /// Initialize the backend. Returns [`LlamaError::BackendAlreadyInitialized`]
21 /// if a `LlamaBackend` is already live in this process.
22 pub fn init() -> Result<Self, LlamaError> {
23 if INITIALIZED.swap(true, Ordering::SeqCst) {
24 return Err(LlamaError::BackendAlreadyInitialized);
25 }
26 // SAFETY: guarded by the atomic above; called at most once at a time.
27 unsafe { ik_llama_cpp_sys::llama_backend_init() };
28 Ok(Self { _private: () })
29 }
30}
31
32impl Drop for LlamaBackend {
33 fn drop(&mut self) {
34 // SAFETY: matches the single `llama_backend_init` above.
35 unsafe { ik_llama_cpp_sys::llama_backend_free() };
36 INITIALIZED.store(false, Ordering::SeqCst);
37 }
38}