From bcc533e9613f098ea7edfd7edb6433b5c70eadc5 Mon Sep 17 00:00:00 2001 From: Tin Svagelj Date: Sat, 16 Sep 2023 20:32:49 +0200 Subject: [PATCH] Clean up shrink_to_fit return type Signed-off-by: Tin Svagelj --- src/details.rs | 16 +++++--- src/lib.rs | 100 +++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 94 insertions(+), 22 deletions(-) diff --git a/src/details.rs b/src/details.rs index 8eaade4..7ce4a35 100644 --- a/src/details.rs +++ b/src/details.rs @@ -142,7 +142,7 @@ pub trait StorageDetails: ImplBase { /// Shrinks tracked area of the allocation tracker to smallest that can fit /// currently stored data. - fn shrink_tracker(state: &mut Self::StorageState) -> Result, LockingError>; + fn shrink_tracker(state: &mut Self::StorageState) -> Self::LockResult>; /// Finds the next free memory region for given layout in the tracker. fn track_next( @@ -314,11 +314,15 @@ impl StorageDetails for ImplDefault { state: &mut Self::StorageState, new_capacity: usize, ) -> Result<(), ContiguousMemoryError> { - state.tracker.borrow_mut().resize(new_capacity) + state + .tracker + .try_borrow_mut() + .map_err(|_| ContiguousMemoryError::TrackerInUse)? + .resize(new_capacity) } - fn shrink_tracker(state: &mut Self::StorageState) -> Result, LockingError> { - Ok(state.tracker.borrow_mut().shrink_to_fit()) + fn shrink_tracker(state: &mut Self::StorageState) -> Option { + state.tracker.borrow_mut().shrink_to_fit() } fn track_next( @@ -409,8 +413,8 @@ impl StorageDetails for ImplUnsafe { state.tracker.resize(new_capacity) } - fn shrink_tracker(state: &mut Self::StorageState) -> Result, LockingError> { - Ok(state.tracker.shrink_to_fit()) + fn shrink_tracker(state: &mut Self::StorageState) -> Option { + state.tracker.shrink_to_fit() } fn track_next( diff --git a/src/lib.rs b/src/lib.rs index 56295d3..6e25501 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -36,7 +36,7 @@ use core::{ ops::Deref, }; -use error::ContiguousMemoryError; +use error::{ContiguousMemoryError, LockingError}; /// A memory container for efficient allocation and storage of contiguous data. /// @@ -150,14 +150,6 @@ impl ContiguousMemoryStorage { Ok(moved) } - /// Shrinks the allocated memory to fit the currently stored data. - pub fn shrink_to_fit(&mut self) -> Result<(), ContiguousMemoryError> { - if let Some(shrunk) = Impl::shrink_tracker(&mut self.inner)? { - self.resize(shrunk)?; - } - Ok(()) - } - /// Returns `true` if the provided value can be stored without growing the /// container. /// @@ -172,8 +164,8 @@ impl ContiguousMemoryStorage { /// let mut storage = UnsafeContiguousMemory::new(0); /// let value = [2, 4, 8, 16]; /// - /// # assert_eq!(storage.can_push(&value).unwrap(), false); - /// if !storage.can_push(&value).unwrap() { + /// # assert_eq!(storage.can_push::>().unwrap(), false); + /// if !storage.can_push::>().unwrap() { /// storage.resize(storage.get_capacity() + size_of_val(&value)); /// /// // ...update old pointers... @@ -192,8 +184,8 @@ impl ContiguousMemoryStorage { /// returned under same conditions. /// /// Unsafe implementation never fails. - pub fn can_push(&self, value: &T) -> Result { - let layout = Layout::for_value(&value); + pub fn can_push(&self) -> Result { + let layout = Layout::new::(); Ok(Impl::peek_next(&self.inner, layout)?.is_some()) } @@ -320,7 +312,44 @@ impl ContiguousMemoryStorage { } } +impl ContiguousMemoryStorage { + /// Shrinks the allocated memory to fit the currently stored data and + /// returns the new capacity. + pub fn shrink_to_fit(&mut self) -> usize { + if let Some(shrunk) = ImplDefault::shrink_tracker(&mut self.inner) { + self.resize(shrunk).expect("unable to shrink container"); + shrunk + } else { + self.capacity.get() + } + } +} + +impl ContiguousMemoryStorage { + /// Shrinks the allocated memory to fit the currently stored data and + /// returns the new capacity. + pub fn shrink_to_fit(&mut self) -> Result { + if let Some(shrunk) = ImplConcurrent::shrink_tracker(&mut self.inner)? { + self.resize(shrunk).expect("unable to shrink container"); + return Ok(shrunk); + } else { + Ok(self.get_capacity()) + } + } +} + impl ContiguousMemoryStorage { + /// Shrinks the allocated memory to fit the currently stored data and + /// returns the new capacity. + pub fn shrink_to_fit(&mut self) -> usize { + if let Some(shrunk) = ImplUnsafe::shrink_tracker(&mut self.inner) { + self.resize(shrunk).expect("unable to shrink container"); + shrunk + } else { + self.capacity + } + } + /// Clones the allocated memory region into a new ContiguousMemoryStorage. /// /// This function isn't unsafe, even though it ignores presence of `Copy` @@ -532,13 +561,13 @@ mod test { } #[test] - fn test_new_contiguous_memory() { + fn construct_contiguous_memory() { let memory = ContiguousMemory::new(1024); assert_eq!(memory.get_capacity(), 1024); } #[test] - fn test_store_and_get_contiguous_memory() { + fn store_and_get() { let mut memory = ContiguousMemory::new(1024); let person_a = Person { @@ -583,7 +612,7 @@ mod test { } #[test] - fn test_resize_contiguous_memory() { + fn resize_manually() { let mut memory = ContiguousMemory::new(512); let person_a = Person { @@ -611,4 +640,43 @@ mod test { assert_eq!(*stored_car.get(), car_a); } + + #[test] + fn resize_automatically() { + let mut memory = ContiguousMemory::new(144); + + memory.push(Person { + name: "Jacky".to_string(), + last_name: "Larsson".to_string(), + }); + memory.push(Person { + name: "Jacky".to_string(), + last_name: "Larsson".to_string(), + }); + memory.push(Person { + name: "Jacky".to_string(), + last_name: "Larsson".to_string(), + }); + assert_eq!(memory.can_push::().unwrap(), false); + + assert_eq!(memory.get_capacity(), 288); + + // 144 + //192 + } + + #[test] + fn add_to_zero_sized() { + let mut memory = ContiguousMemory::new(0); + + let person = Person { + name: "Jacky".to_string(), + last_name: "Larsson".to_string(), + }; + + let stored_person = memory.push(person.clone()); + + assert_eq!(memory.get_capacity(), 48); + assert_eq!(*stored_person.get(), person); + } }