From 7b1f035dbc14c808f1f03be92edbb02208d2fd8f Mon Sep 17 00:00:00 2001 From: Dragoljub Duric Date: Wed, 7 Feb 2024 15:28:15 +0000 Subject: [PATCH 01/11] . --- src/btreemap.rs | 42 ++++++++++++++++++++++++++++-------------- 1 file changed, 28 insertions(+), 14 deletions(-) diff --git a/src/btreemap.rs b/src/btreemap.rs index 9ce8318c..715de583 100644 --- a/src/btreemap.rs +++ b/src/btreemap.rs @@ -166,19 +166,8 @@ where } } - /// Creates a new instance a `BTreeMap`. - /// - /// The given `memory` is assumed to be exclusively reserved for this data - /// structure and that it starts at address zero. Typically `memory` will - /// be an instance of `RestrictedMemory`. - /// - /// When initialized, the data structure has the following memory layout: - /// - /// | BTreeHeader | Allocator | ... free memory for nodes | - /// - /// See `Allocator` for more details on its own memory layout. - pub fn new(memory: M) -> Self { - let page_size = match (K::BOUND, V::BOUND) { + fn page_size() -> PageSize { + match (K::BOUND, V::BOUND) { // The keys and values are both bounded. ( StorableBound::Bounded { @@ -201,7 +190,22 @@ where } // Use a default page size. _ => PageSize::Value(DEFAULT_PAGE_SIZE), - }; + } + } + + /// Creates a new instance a `BTreeMap`. + /// + /// The given `memory` is assumed to be exclusively reserved for this data + /// structure and that it starts at address zero. Typically `memory` will + /// be an instance of `RestrictedMemory`. + /// + /// When initialized, the data structure has the following memory layout: + /// + /// | BTreeHeader | Allocator | ... free memory for nodes | + /// + /// See `Allocator` for more details on its own memory layout. + pub fn new(memory: M) -> Self { + let page_size = Self::page_size(); let btree = Self { root_addr: NULL, @@ -561,6 +565,16 @@ where Self::new(mem) } + pub fn clear_new(&mut self) { + self.root_addr = NULL; + self.length = 0; + /*self.allocator = Allocator::new( + //self.allocator.into_memory(), + Address::from(ALLOCATOR_OFFSET as u64), + Self::page_size().get().into(), + )*/ + } + /// Returns the first key-value pair in the map. The key in this /// pair is the minimum key in the map. pub fn first_key_value(&self) -> Option<(K, V)> { From 5d9e7aaa851fe046d3c55e55958c55ff1cc6d6f3 Mon Sep 17 00:00:00 2001 From: Dragoljub Duric Date: Tue, 20 Feb 2024 14:38:00 +0000 Subject: [PATCH 02/11] . --- src/btreemap.rs | 8 +++----- src/btreemap/allocator.rs | 11 +++++++++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/btreemap.rs b/src/btreemap.rs index 715de583..5f2fa6df 100644 --- a/src/btreemap.rs +++ b/src/btreemap.rs @@ -560,19 +560,17 @@ where } /// Removes all elements from the map. + #[deprecated(since = "0.6.3", note = "please use `clear_new` instead")] pub fn clear(self) -> Self { let mem = self.allocator.into_memory(); Self::new(mem) } + /// Removes all elements from the map. pub fn clear_new(&mut self) { self.root_addr = NULL; self.length = 0; - /*self.allocator = Allocator::new( - //self.allocator.into_memory(), - Address::from(ALLOCATOR_OFFSET as u64), - Self::page_size().get().into(), - )*/ + self.allocator.clear(); } /// Returns the first key-value pair in the map. The key in this diff --git a/src/btreemap/allocator.rs b/src/btreemap/allocator.rs index 957441b0..a24a9e81 100644 --- a/src/btreemap/allocator.rs +++ b/src/btreemap/allocator.rs @@ -94,6 +94,17 @@ impl Allocator { allocator } + // Deallocate all allocated chunks. + pub fn clear(&mut self) { + // Create the initial memory chunk and save it directly after the allocator's header. + let chunk = ChunkHeader::null(); + chunk.save(self.free_list_head, &self.memory); + + self.num_allocated_chunks = 0; + + self.save() + } + /// Load an allocator from memory at the given `addr`. pub fn load(memory: M, addr: Address) -> Self { let header: AllocatorHeader = read_struct(addr, &memory); From 5f1d46228e540f1d6522a49ea663d16ac6fe0f5d Mon Sep 17 00:00:00 2001 From: Dragoljub Duric Date: Wed, 21 Feb 2024 10:53:44 +0000 Subject: [PATCH 03/11] . --- src/btreemap.rs | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/src/btreemap.rs b/src/btreemap.rs index e3326b96..5c7cc128 100644 --- a/src/btreemap.rs +++ b/src/btreemap.rs @@ -166,8 +166,19 @@ where } } - fn page_size() -> PageSize { - match (K::BOUND, V::BOUND) { + /// Creates a new instance a `BTreeMap`. + /// + /// The given `memory` is assumed to be exclusively reserved for this data + /// structure and that it starts at address zero. Typically `memory` will + /// be an instance of `RestrictedMemory`. + /// + /// When initialized, the data structure has the following memory layout: + /// + /// | BTreeHeader | Allocator | ... free memory for nodes | + /// + /// See `Allocator` for more details on its own memory layout. + pub fn new(memory: M) -> Self { + let page_size = match (K::BOUND, V::BOUND) { // The keys and values are both bounded. ( StorableBound::Bounded { @@ -190,22 +201,7 @@ where } // Use a default page size. _ => PageSize::Value(DEFAULT_PAGE_SIZE), - } - } - - /// Creates a new instance a `BTreeMap`. - /// - /// The given `memory` is assumed to be exclusively reserved for this data - /// structure and that it starts at address zero. Typically `memory` will - /// be an instance of `RestrictedMemory`. - /// - /// When initialized, the data structure has the following memory layout: - /// - /// | BTreeHeader | Allocator | ... free memory for nodes | - /// - /// See `Allocator` for more details on its own memory layout. - pub fn new(memory: M) -> Self { - let page_size = Self::page_size(); + }; let btree = Self { root_addr: NULL, From f0ed4bdd008d1ebbad972ead4112c34d4d1eef15 Mon Sep 17 00:00:00 2001 From: Dragoljub Duric Date: Thu, 22 Feb 2024 15:32:07 +0000 Subject: [PATCH 04/11] . --- src/btreemap/allocator.rs | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/src/btreemap/allocator.rs b/src/btreemap/allocator.rs index a24a9e81..ee978d14 100644 --- a/src/btreemap/allocator.rs +++ b/src/btreemap/allocator.rs @@ -97,6 +97,7 @@ impl Allocator { // Deallocate all allocated chunks. pub fn clear(&mut self) { // Create the initial memory chunk and save it directly after the allocator's header. + self.free_list_head = self.header_addr + AllocatorHeader::size(); let chunk = ChunkHeader::null(); chunk.save(self.free_list_head, &self.memory); @@ -412,6 +413,40 @@ mod test { assert_eq!(allocator.num_allocated_chunks, 0); } + #[test] + fn allocate_then_clear() { + let mem = make_memory(); + let allocation_size = Bytes::from(16u64); + let allocator_addr = Address::from(0); + + let mut allocator = Allocator::new(mem.clone(), allocator_addr, allocation_size); + + allocator.allocate(); + allocator.allocate(); + + assert_eq!( + allocator.free_list_head, + allocator_addr + + AllocatorHeader::size() + + allocator.chunk_size() + + allocator.chunk_size() + ); + allocator.clear(); + assert_eq!( + allocator.free_list_head, + allocator_addr + AllocatorHeader::size() + ); + assert_eq!(allocator.num_allocated_chunks, 0); + + // Load and reload to verify that the data is the same. + let allocator = Allocator::load(mem, allocator_addr); + assert_eq!( + allocator.free_list_head, + allocator_addr + AllocatorHeader::size() + ); + assert_eq!(allocator.num_allocated_chunks, 0); + } + #[test] fn allocate_deallocate_2() { let mem = make_memory(); From 3796caf2e6acecec21b4b63e1156c20d2f3a403b Mon Sep 17 00:00:00 2001 From: Dragoljub Duric Date: Thu, 22 Feb 2024 15:45:32 +0000 Subject: [PATCH 05/11] Add test for BTreeMap::clear_new(). --- src/btreemap.rs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/btreemap.rs b/src/btreemap.rs index 5c7cc128..8a1e6502 100644 --- a/src/btreemap.rs +++ b/src/btreemap.rs @@ -3037,4 +3037,24 @@ mod test { let btree: BTreeMap = BTreeMap::init(btree.into_memory()); assert_eq!(btree.get(&T), Some(T)); } + + #[test] + fn test_clear_new() { + let mem = make_memory(); + let mut btree: BTreeMap, Blob<4>, _> = BTreeMap::init(mem); + btree.insert( + [1u8; 4].as_slice().try_into().unwrap(), + [1u8; 4].as_slice().try_into().unwrap(), + ); + + assert_ne!(btree.len(), 0); + assert_ne!(btree.allocator.num_allocated_chunks(), 0); + assert_ne!(btree.root_addr, NULL); + + btree.clear_new(); + + assert_eq!(btree.len(), 0); + assert_eq!(btree.allocator.num_allocated_chunks(), 0); + assert_eq!(btree.root_addr, NULL); + } } From 2c8fbc02953d2b5e205cfc5bf1200aa4e3a7d6af Mon Sep 17 00:00:00 2001 From: Dragoljub Duric Date: Thu, 22 Feb 2024 15:47:48 +0000 Subject: [PATCH 06/11] . --- src/btreemap/allocator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/btreemap/allocator.rs b/src/btreemap/allocator.rs index ee978d14..22c7b615 100644 --- a/src/btreemap/allocator.rs +++ b/src/btreemap/allocator.rs @@ -94,7 +94,7 @@ impl Allocator { allocator } - // Deallocate all allocated chunks. + /// Deallocate all allocated chunks. pub fn clear(&mut self) { // Create the initial memory chunk and save it directly after the allocator's header. self.free_list_head = self.header_addr + AllocatorHeader::size(); From fae91be622b6f17ae0d25a44c1f2e7e0dded3537 Mon Sep 17 00:00:00 2001 From: Dragoljub Duric Date: Tue, 27 Feb 2024 09:36:39 +0000 Subject: [PATCH 07/11] fix tests --- src/btreemap.rs | 14 ++++++++++---- src/btreemap/allocator.rs | 20 ++++++++------------ 2 files changed, 18 insertions(+), 16 deletions(-) diff --git a/src/btreemap.rs b/src/btreemap.rs index 8a1e6502..f6e7fdc2 100644 --- a/src/btreemap.rs +++ b/src/btreemap.rs @@ -107,6 +107,7 @@ where _phantom: PhantomData<(K, V)>, } +#[derive(PartialEq, Debug)] /// The packed header size must be <= ALLOCATOR_OFFSET. struct BTreeHeader { version: Version, @@ -567,6 +568,7 @@ where self.root_addr = NULL; self.length = 0; self.allocator.clear(); + self.save(); } /// Returns the first key-value pair in the map. The key in this @@ -3041,7 +3043,7 @@ mod test { #[test] fn test_clear_new() { let mem = make_memory(); - let mut btree: BTreeMap, Blob<4>, _> = BTreeMap::init(mem); + let mut btree: BTreeMap, Blob<4>, _> = BTreeMap::new(mem.clone()); btree.insert( [1u8; 4].as_slice().try_into().unwrap(), [1u8; 4].as_slice().try_into().unwrap(), @@ -3053,8 +3055,12 @@ mod test { btree.clear_new(); - assert_eq!(btree.len(), 0); - assert_eq!(btree.allocator.num_allocated_chunks(), 0); - assert_eq!(btree.root_addr, NULL); + let header_actual = BTreeMap::, Blob<4>, _>::read_header(&mem); + + BTreeMap::, Blob<4>, _>::new(mem.clone()); + + let header_expected = BTreeMap::, Blob<4>, _>::read_header(&mem); + + assert_eq!(header_actual, header_expected); } } diff --git a/src/btreemap/allocator.rs b/src/btreemap/allocator.rs index 22c7b615..1bc94993 100644 --- a/src/btreemap/allocator.rs +++ b/src/btreemap/allocator.rs @@ -46,6 +46,7 @@ pub struct Allocator { } #[repr(C, packed)] +#[derive(PartialEq, Debug)] struct AllocatorHeader { magic: [u8; 3], version: u8, @@ -432,19 +433,14 @@ mod test { + allocator.chunk_size() ); allocator.clear(); - assert_eq!( - allocator.free_list_head, - allocator_addr + AllocatorHeader::size() - ); - assert_eq!(allocator.num_allocated_chunks, 0); - // Load and reload to verify that the data is the same. - let allocator = Allocator::load(mem, allocator_addr); - assert_eq!( - allocator.free_list_head, - allocator_addr + AllocatorHeader::size() - ); - assert_eq!(allocator.num_allocated_chunks, 0); + let header_actual: AllocatorHeader = read_struct(allocator_addr, &mem); + + Allocator::new(mem.clone(), allocator_addr, allocation_size); + + let header_expected: AllocatorHeader = read_struct(allocator_addr, &mem); + + assert_eq!(header_actual, header_expected); } #[test] From d848d1cb1bc8f4dcde30823a7d5d41b286d87d95 Mon Sep 17 00:00:00 2001 From: Dragoljub Djuric Date: Tue, 27 Feb 2024 13:23:20 +0100 Subject: [PATCH 08/11] Update src/btreemap/allocator.rs Co-authored-by: Islam El-Ashi --- src/btreemap/allocator.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/btreemap/allocator.rs b/src/btreemap/allocator.rs index 1bc94993..e7f61a99 100644 --- a/src/btreemap/allocator.rs +++ b/src/btreemap/allocator.rs @@ -415,7 +415,7 @@ mod test { } #[test] - fn allocate_then_clear() { + fn clear_deallocates_all_allocated_chunks { let mem = make_memory(); let allocation_size = Bytes::from(16u64); let allocator_addr = Address::from(0); From 9ca3ef0ef40eeae8aa702d093573112466c39fcf Mon Sep 17 00:00:00 2001 From: Dragoljub Duric Date: Tue, 27 Feb 2024 12:35:53 +0000 Subject: [PATCH 09/11] . --- src/btreemap.rs | 23 ++++++++++++++++++++++- src/btreemap/allocator.rs | 14 ++++---------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/src/btreemap.rs b/src/btreemap.rs index f6e7fdc2..f98ce390 100644 --- a/src/btreemap.rs +++ b/src/btreemap.rs @@ -3041,7 +3041,7 @@ mod test { } #[test] - fn test_clear_new() { + fn test_clear_new_bounded_type() { let mem = make_memory(); let mut btree: BTreeMap, Blob<4>, _> = BTreeMap::new(mem.clone()); btree.insert( @@ -3063,4 +3063,25 @@ mod test { assert_eq!(header_actual, header_expected); } + + #[test] + fn test_clear_new_unbounded_type() { + let mem = make_memory(); + let mut btree: BTreeMap = BTreeMap::new(mem.clone()); + btree.insert("asd".try_into().unwrap(), "bce".try_into().unwrap()); + + assert_ne!(btree.len(), 0); + assert_ne!(btree.allocator.num_allocated_chunks(), 0); + assert_ne!(btree.root_addr, NULL); + + btree.clear_new(); + + let header_actual = BTreeMap::::read_header(&mem); + + BTreeMap::::new(mem.clone()); + + let header_expected = BTreeMap::::read_header(&mem); + + assert_eq!(header_actual, header_expected); + } } diff --git a/src/btreemap/allocator.rs b/src/btreemap/allocator.rs index e7f61a99..68544599 100644 --- a/src/btreemap/allocator.rs +++ b/src/btreemap/allocator.rs @@ -77,21 +77,15 @@ impl Allocator { /// |__________| |____ NULL /// pub fn new(memory: M, addr: Address, allocation_size: Bytes) -> Self { - let free_list_head = addr + AllocatorHeader::size(); - - // Create the initial memory chunk and save it directly after the allocator's header. - let chunk = ChunkHeader::null(); - chunk.save(free_list_head, &memory); - - let allocator = Self { + let mut allocator = Self { header_addr: addr, allocation_size, num_allocated_chunks: 0, - free_list_head, + free_list_head: NULL, // Will be set in `allocator.clear()` below. memory, }; - allocator.save(); + allocator.clear(); allocator } @@ -415,7 +409,7 @@ mod test { } #[test] - fn clear_deallocates_all_allocated_chunks { + fn clear_deallocates_all_allocated_chunks() { let mem = make_memory(); let allocation_size = Bytes::from(16u64); let allocator_addr = Address::from(0); From eb0b0c6c0d00bbc6e839574ce93c507bd207e2a0 Mon Sep 17 00:00:00 2001 From: Dragoljub Duric Date: Tue, 27 Feb 2024 12:38:02 +0000 Subject: [PATCH 10/11] clippy --- src/btreemap.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/btreemap.rs b/src/btreemap.rs index f98ce390..ed80fa12 100644 --- a/src/btreemap.rs +++ b/src/btreemap.rs @@ -3068,7 +3068,7 @@ mod test { fn test_clear_new_unbounded_type() { let mem = make_memory(); let mut btree: BTreeMap = BTreeMap::new(mem.clone()); - btree.insert("asd".try_into().unwrap(), "bce".try_into().unwrap()); + btree.insert("asd".into(), "bce".into()); assert_ne!(btree.len(), 0); assert_ne!(btree.allocator.num_allocated_chunks(), 0); From 7a0aa63d7630faa84c227d2f61b4415f43be2fd3 Mon Sep 17 00:00:00 2001 From: Dragoljub Duric Date: Mon, 4 Mar 2024 13:48:17 +0000 Subject: [PATCH 11/11] . --- src/btreemap.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/btreemap.rs b/src/btreemap.rs index ed80fa12..f4ca151c 100644 --- a/src/btreemap.rs +++ b/src/btreemap.rs @@ -3044,6 +3044,7 @@ mod test { fn test_clear_new_bounded_type() { let mem = make_memory(); let mut btree: BTreeMap, Blob<4>, _> = BTreeMap::new(mem.clone()); + btree.insert( [1u8; 4].as_slice().try_into().unwrap(), [1u8; 4].as_slice().try_into().unwrap(),