1mod access_graph;
6pub mod artifacts;
7#[path = "benchmark_statistics.rs"]
8pub mod benchmark;
9mod buffer_pool;
10pub mod bundle;
11mod dependency_frontier;
12pub mod image;
13pub mod inference;
14pub mod jobs;
15pub mod plan_cache;
16pub mod residency;
17mod runtime;
18#[allow(dead_code)]
19mod sys;
20mod target;
21pub mod tensor;
22pub use access_graph::{AccessGraph, AccessView};
23pub use buffer_pool::{BufferPool, PooledBuffer};
24pub use runtime::*;
25pub mod execution;
27#[path = "loom/model.rs"]
28pub mod model;
29pub use execution::{Access, Completion, Runtime};
30pub mod gpu {
33 pub use crate::runtime::*;
34}
35pub use target::{TARGET_FAMILY, TARGET_KEY, Target};
36pub mod loom;
37#[cfg(feature = "npu")]
38pub mod npu;
39
40#[cfg(doctest)]
43#[doc = include_str!("../README.md")]
44pub struct Readme;
45
46#[derive(Debug, thiserror::Error)]
48#[non_exhaustive]
49pub enum Error {
50 #[error("resource busy: {0}")]
52 Busy(String),
53 #[error("unsupported capability: {0}")]
55 Unsupported(String),
56 #[error("device execution failed: {0}")]
58 DeviceLost(String),
59 #[error("{backend} {operation} failed ({code}): {message}")]
61 Backend {
62 backend: &'static str,
64 operation: &'static str,
66 code: i32,
68 message: Box<str>,
71 },
72 #[error("{source}")]
74 Execution {
75 #[source]
77 source: std::sync::Arc<Error>,
78 },
79 #[error("execution cancelled")]
81 Cancelled,
82 #[error("{0}")]
84 Message(String),
85 #[error("Loom compilation failed: {message}")]
87 Compile {
88 message: String,
90 diagnostics: Vec<loom::Diagnostic>,
92 },
93 #[error("{0}")]
95 Io(#[from] std::io::Error),
96 #[error("{0}")]
98 Json(#[from] serde_json::Error),
99 #[error("{0}")]
101 Library(#[from] libloading::Error),
102 #[error("{0}")]
104 Download(#[source] Box<ureq::Error>),
105 #[error("{context}: {message}")]
107 Runtime {
108 context: String,
110 code: i32,
112 message: String,
114 },
115 #[error("{context}: {source}")]
117 Context {
118 context: String,
120 #[source]
121 source: Box<Error>,
123 },
124}
125impl Error {
126 pub fn context(self, context: impl Into<String>) -> Self {
128 Self::Context {
129 context: context.into(),
130 source: Box::new(self),
131 }
132 }
133}
134pub type Result<T> = std::result::Result<T, Error>;
136
137pub mod runner;
138
139pub(crate) fn cached_init<T: Clone>(
141 cache: &std::sync::Mutex<Option<T>>,
142 initialize: impl FnOnce() -> Result<T>,
143) -> Result<T> {
144 let mut cached = cache
145 .lock()
146 .map_err(|_| Error::Message("initialization cache poisoned".into()))?;
147 if let Some(value) = cached.as_ref() {
148 return Ok(value.clone());
149 }
150 let value = initialize()?;
151 *cached = Some(value.clone());
152 Ok(value)
153}
154
155#[cfg(test)]
156mod initialization_tests {
157 #[test]
158 fn failures_retry_and_concurrent_success_initializes_once() {
159 use std::sync::{
160 Mutex,
161 atomic::{AtomicUsize, Ordering},
162 };
163 let cache = Mutex::new(None);
164 assert!(
165 super::cached_init(&cache, || Err::<usize, _>(super::Error::Message(
166 "transient".into()
167 )))
168 .is_err()
169 );
170 let calls = AtomicUsize::new(0);
171 std::thread::scope(|scope| {
172 for _ in 0..8 {
173 scope.spawn(|| {
174 assert_eq!(
175 super::cached_init(&cache, || {
176 calls.fetch_add(1, Ordering::Relaxed);
177 Ok(42)
178 })
179 .unwrap(),
180 42
181 );
182 });
183 }
184 });
185 assert_eq!(calls.load(Ordering::Relaxed), 1);
186 }
187}