Browse Source

Move remove_at to Bookkeeper

ticki 8 years ago
parent
commit
2443f0e4bf
5 changed files with 54 additions and 25 deletions
  1. 1 1
      Cargo.toml
  2. 10 1
      shim/Cargo.toml
  3. 3 0
      shim/src/lib.rs
  4. 31 3
      src/bookkeeper.rs
  5. 9 20
      src/vec.rs

+ 1 - 1
Cargo.toml

@@ -29,7 +29,7 @@ debug-assertions = false
 codegen-units = 1
 
 [features]
-default = ["allocator"] #clippy
+default = ["allocator", "clippy"]
 
 allocator = []
 debug_tools = []

+ 10 - 1
shim/Cargo.toml

@@ -1,4 +1,13 @@
 [package]
 name = "ralloc_shim"
 version = "0.1.0"
-authors = ["Jeremy Soller <jackpot51@gmail.com>"]
+authors = ["Jeremy Soller <jackpot51@gmail.com>", "Ticki"]
+
+[profile.release]
+panic = "abort"
+opt-level = 3
+debug = false
+rpath = false
+lto = true
+debug-assertions = false
+codegen-units = 1

+ 3 - 0
shim/src/lib.rs

@@ -1,6 +1,9 @@
+//! Symbols and externs that ralloc depends on.
+
 #![crate_name="ralloc_shim"]
 #![crate_type="lib"]
 #![feature(lang_items)]
+#![warn(missing_docs)]
 #![no_std]
 
 extern "C" {

+ 31 - 3
src/bookkeeper.rs

@@ -168,7 +168,7 @@ impl Bookkeeper {
             }
         }).next() {
             if self.pool[n].is_empty() {
-                let _ = self.pool.remove_at(n); //for empty alignment invariant
+                let _ = self.remove_at(n); //for empty alignment invariant
             }
 
             let (res, excessive) = b.split(size);
@@ -404,7 +404,7 @@ impl Bookkeeper {
             // the current block.
             if mergable {
                 log!(self.pool;ind, "  Merge");
-                block.merge_right(&mut self.pool.remove_at(ind_right)).unwrap();
+                block.merge_right(&mut self.remove_at(ind_right)).unwrap();
                 // Merge succeeded.
 
                 // Place the excessive block back.
@@ -452,7 +452,7 @@ impl Bookkeeper {
 
         // Try to merge it with the block to the right.
         if right_ind < self.pool.len() && block.left_to(&self.pool[right_ind]) {
-            block.merge_right(&mut self.pool.remove_at(right_ind)).unwrap();
+            block.merge_right(&mut self.remove_at(right_ind)).unwrap();
             // The merging succeeded. We proceed to try to close in the possible gap.
             if ind != 0 && self.pool[ind-1].merge_right(&mut block).is_ok() {
                 self.check();
@@ -752,6 +752,34 @@ impl Bookkeeper {
         self.check();
     }
 
+    /// Remove a block.
+    fn remove_at(&mut self, ind: usize) -> Block {
+        if ind == self.pool.len() - 1 {
+            let ret = self.pool[ind].pop();
+            // Make sure there are no trailing empty blocks.
+            let new_len = self.pool.len() - self.pool.iter().rev().take_while(|x| x.is_empty()).count();
+
+            // Truncate the vector.
+            self.pool.truncate(new_len);
+            ret
+        } else {
+            // Calculate the upper and lower bound
+            let empty = self.pool[ind + 1].empty_left();
+            let empty2 = empty.empty_left();
+
+            // Replace the block at `ind` with the left empty block from `ind + 1`.
+            let ret = mem::replace(&mut self.pool[ind], empty);
+            // Iterate over the pool from `ind` and down.
+            let skip = self.pool.len() - ind;
+            for place in self.pool.iter_mut().rev().skip(skip).take_while(|x| x.is_empty()) {
+                // Empty the blocks.
+                *place = empty2.empty_left();
+            }
+
+            ret
+        }
+    }
+
     /// Call the OOM handler.
     ///
     /// This is used one out-of-memory errors, and will never return. Usually, it simply consists

+ 9 - 20
src/vec.rs

@@ -105,6 +105,15 @@ impl<T: Leak> Vec<T> {
         }
     }
 
+    /// Truncate this vector.
+    ///
+    /// This is O(1).
+    pub fn truncate(&mut self, len: usize) {
+        assert!(len <= self.len, "Out of bound.");
+
+        self.len = len;
+    }
+
     pub fn grow(&mut self) {
         if self.len < self.cap {
             self.len += 1;
@@ -125,26 +134,6 @@ impl<T: Leak> Vec<T> {
     }
 }
 
-impl Vec<Block> {
-    pub fn remove_at(&mut self, index: usize) -> Block {
-        assert!(index < self.len);
-        if index == self.len - 1 {
-            let ret = self[index].pop();
-            self.len -= self.iter().rev().take_while(|x| x.is_empty()).count();
-            ret
-        } else {
-            let empty = self[index+1].empty_left();
-            let empty2 = empty.empty_left();
-            let ret = mem::replace(&mut self[index], empty);
-            let skip = self.len - index;
-            for place in self.iter_mut().rev().skip(skip).take_while(|x| x.is_empty()) {
-                *place = empty2.empty_left();
-            }
-            ret
-        }
-    }
-}
-
 /// Cast this vector to the respective block.
 impl<T: Leak> From<Vec<T>> for Block {
     fn from(from: Vec<T>) -> Block {