diff --git a/src/memory_manager.rs b/src/memory_manager.rs index 567d3559..a84075be 100644 --- a/src/memory_manager.rs +++ b/src/memory_manager.rs @@ -155,6 +155,15 @@ impl MemoryManager { memory_manager: self.inner.clone(), } } + + /// Returns the underlying memory. + /// + /// # Returns + /// - The underlying memory, if there is exactly one strong reference to the memory manager. Please see [`Rc::try_unwrap`](https://doc.rust-lang.org/std/rc/struct.Rc.html#method.try_unwrap) for more details. + /// - None otherwise. + pub fn into_memory(self) -> Option { + Rc::into_inner(self.inner).map(|inner| inner.into_inner().into_memory()) + } } #[repr(C, packed)] @@ -419,6 +428,11 @@ impl MemoryManagerInner { // Ceiling division. (num_pages + self.bucket_size_in_pages as u64 - 1) / self.bucket_size_in_pages as u64 } + + // Returns the underlying memory. + pub fn into_memory(self) -> M { + self.memory + } } struct Segment { diff --git a/src/tests.rs b/src/tests.rs index 6bd1caee..3d138d68 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -1,4 +1,5 @@ use super::*; +use crate::memory_manager::{MemoryId, MemoryManager}; use std::cell::RefCell; use std::rc::Rc; @@ -48,3 +49,20 @@ fn vec_exposes_init_err() { #[allow(unused_imports)] use crate::vec::InitError; } + +#[test] +fn should_be_able_to_recover_memory_from_memory_manager() { + let raw_memory = DefaultMemoryImpl::default(); + let memory_manager = MemoryManager::init(raw_memory); + let recovered_memory = memory_manager.into_memory(); + assert!(recovered_memory.is_some()); +} + +#[test] +fn should_fail_to_recover_memory_from_memory_manager_if_memory_is_in_use() { + let raw_memory = DefaultMemoryImpl::default(); + let memory_manager = MemoryManager::init(raw_memory); + let _a_virtual_memory = memory_manager.get(MemoryId::new(0)); + let recovered_memory = memory_manager.into_memory(); + assert!(recovered_memory.is_none()); +}