icydb_core/db/memory_runtime/
mod.rs1#[cfg(test)]
8mod tests;
9
10use ic_memory::{DefaultMemoryImpl, MemoryRuntime, RuntimeMemory, RuntimeOpenError};
11use std::{cell::OnceCell, rc::Rc};
12
13thread_local! {
14 static MEMORY_RUNTIME: OnceCell<Rc<MemoryRuntime<DefaultMemoryImpl>>> = const { OnceCell::new() };
15}
16
17#[derive(Clone, Copy, Debug, Eq, thiserror::Error, PartialEq)]
19pub enum MemoryRuntimeBindingError {
20 #[error("memory runtime has not completed bootstrap")]
22 NotBootstrapped,
23 #[error("IcyDB is already bound to a different memory runtime")]
25 AlreadyBound,
26}
27
28pub fn bind_memory_runtime(
34 runtime: Rc<MemoryRuntime<DefaultMemoryImpl>>,
35) -> Result<(), MemoryRuntimeBindingError> {
36 if !runtime.is_bootstrapped() {
37 return Err(MemoryRuntimeBindingError::NotBootstrapped);
38 }
39 MEMORY_RUNTIME.with(|bound| {
40 if let Some(existing) = bound.get() {
41 return if Rc::ptr_eq(existing, &runtime) {
42 Ok(())
43 } else {
44 Err(MemoryRuntimeBindingError::AlreadyBound)
45 };
46 }
47 bound
48 .set(runtime)
49 .map_err(|_| MemoryRuntimeBindingError::AlreadyBound)
50 })
51}
52
53#[must_use]
55pub fn memory_runtime() -> Option<Rc<MemoryRuntime<DefaultMemoryImpl>>> {
56 MEMORY_RUNTIME.with(|bound| bound.get().cloned())
57}
58
59#[doc(hidden)]
61pub fn open_memory(stable_key: &str) -> Result<RuntimeMemory<DefaultMemoryImpl>, RuntimeOpenError> {
62 memory_runtime()
63 .ok_or(RuntimeOpenError::NotBootstrapped)?
64 .open_memory(stable_key)
65}