crates/mimir-graph/src/runtime.rs
//! Process-wide GraphBLAS state: init once, thread count, version.
use std::sync::OnceLock;
use crate::error::{Error, Result, grb};
/// Major version of the C library the checked-in bindings were generated from.
pub const EXPECTED_MAJOR: i32 = 7;
static INIT: OnceLock<std::result::Result<(i32, i32, i32), Error>> = OnceLock::new();
/// Initialise GraphBLAS (`GrB_init(GrB_NONBLOCKING)`) once per process and
/// check the linked library's major version. Every constructor in this crate
/// calls it, so calling it yourself is only needed to surface the error early.
pub fn init() -> Result<()> {
INIT.get_or_init(|| {
grb!(GrB_init(graphblas_sys::GrB_NONBLOCKING))?;
let v = library_version_raw()?;
if v.0 != EXPECTED_MAJOR {
return Err(Error::Version {
found: v,
expected_major: EXPECTED_MAJOR,
});
}
Ok(v)
})
.clone()
.map(|_| ())
}
fn library_version_raw() -> Result<(i32, i32, i32)> {
let mut v = [0i32; 3];
// Variadic in C; GxB_LIBRARY_VERSION writes three ints.
grb!(GxB_Global_Option_get(
graphblas_sys::GxB_LIBRARY_VERSION,
v.as_mut_ptr()
))?;
Ok((v[0], v[1], v[2]))
}
/// `(major, minor, sub)` of the linked libgraphblas.
pub fn library_version() -> Result<(i32, i32, i32)> {
init()?;
INIT.get()
.cloned()
.unwrap_or(Err(Error::invalid("GraphBLAS not initialised")))
}
/// Maximum OpenMP threads GraphBLAS uses per call (global setting).
pub fn set_threads(n: i32) -> Result<()> {
init()?;
if n < 1 {
return Err(Error::invalid(format!("thread count {n} < 1")));
}
grb!(GxB_Global_Option_set_INT32(
graphblas_sys::GxB_GLOBAL_NTHREADS,
n
))
}
/// Current global thread limit.
pub fn threads() -> Result<i32> {
init()?;
let mut n = 0i32;
grb!(GxB_Global_Option_get_INT32(
graphblas_sys::GxB_GLOBAL_NTHREADS,
&mut n
))?;
Ok(n)
}
/// `GrB_finalize`. GraphBLAS cannot be initialised again afterwards in the
/// same process, and every live [`Matrix`](crate::Matrix)/[`Vector`](crate::Vector)
/// would dangle.
///
/// # Safety
/// No GraphBLAS handle may be alive or created after this call.
pub unsafe fn finalize() -> Result<()> {
grb!(GrB_finalize())
}