Selaa lähdekoodia

Implement first-fit searching.

- Instead of relying on newtypes implementing `Search` implement it
  directly.
ticki 8 vuotta sitten
vanhempi
commit
0c1b73cdf2
2 muutettua tiedostoa jossa 29 lisäystä ja 33 poistoa
  1. 8 23
      src/bk/pool.rs
  2. 21 10
      src/bk/search.rs

+ 8 - 23
src/bk/pool.rs

@@ -10,38 +10,23 @@ struct Pool {
 }
 
 impl Pool {
-    /// Search the block pool for a particular block.
+    /// Search the block pool with a particular searcher.
     ///
     /// The outline of the algorithm is this: We start by shortcutting from the top level until we
-    /// overshoot, then we repeat on the next level starting at the last non-overshot shortcut from
-    /// the previous level.
+    /// need to refine (which is determined by the serarcher), then we repeat on the next level
+    /// starting at the last refined shortcut from the previous level. At the lowest level, we go
+    /// forward until we find a match.
+    ///
+    /// A "lookback", i.e. the refined nodes of every level is stored in the returned value.
     ///
     /// # Example
     ///
-    /// If we look for 8, we start in the top level and follow until we hit 9.
+    /// If we look for block 8, we start in the top level and follow until we hit 9.
     ///     ==================> [6] --- overshoot ----> [9] -----------> NIL
     ///     ------------------> [6] ==> [7] ----------> [9] -----------> NIL
     ///     ----------> [5] --> [6] ==> [7] ----------> [9] --> [10] --> NIL
     ///     --> [1] --> [5] --> [6] --> [7] ==> [8] --> [9] --> [10] --> NIL
-    fn search(&mut self, block: &Block) -> Seek {
-        log!(DEBUG, "Searching the block pool for block {:?}...", block);
-
-        // Use `BlockSearcher` for this.
-        self.search_with(search::BlockSearcher {
-            needle: block,
-        }).unwrap()
-        // TODO: Find a way to fix this unwrap.
-    }
-
-    /// Search the block pool with a particular searcher.
-    ///
-    /// The outline of the algorithm is this: We start by shortcutting from the top level until we
-    /// need to refine (which is determined by the serarcher), then we repeat on the next level
-    /// starting at the last refined shortcut from the previous level. At the lowest level, we go
-    /// forward until we find a match.
-    ///
-    /// A "lookback", i.e. the refined nodes of every level is stored in the returned value.
-    fn search_with<S: Search>(&mut self, searcher: S) -> Result<Seek, ()> {
+    fn search<S: Search>(&mut self, searcher: S) -> Result<Seek, ()> {
         // We start by an uninitialized value, which we fill out.
         let mut seek = unsafe { mem::uninitialized() };
 

+ 21 - 10
src/bk/search.rs

@@ -2,7 +2,7 @@
 
 use bk::node::Node;
 use bk::shortcut::Shortcut;
-use block::Block;
+use block::{self, Block};
 
 pub trait Search {
     /// Determine if this shortcut skips the needle.
@@ -17,18 +17,13 @@ pub trait Search {
     fn is_match(self, node: &Node) -> bool;
 }
 
-#[derive(Copy, Clone)]
-pub struct BlockSearcher<'a> {
-    /// The target block.
-    needle: &'a Block,
-}
-
-impl<'a> Search for BlockSearcher {
+/// Search for a block.
+impl<'a> Search for &'a Block {
     fn refine(self, shortcut: &Shortcut) -> bool {
         if let Some(next) = shortcut.next {
             // We refine if the next block is above our needle, and hence not satisfying our
             // search condition.
-            next.block > self.needle
+            next.block > self
         } else {
             // If the shortcut has no successor, we have to refine.
             true
@@ -39,7 +34,7 @@ impl<'a> Search for BlockSearcher {
         if let Some(next) = node.next {
             // We refine if the next block is above our needle, and hence not satisfying our
             // search condition.
-            next.block > self.needle
+            next.block > self
         } else {
             // If the shortcut has no successor (i.e. it is the last block in the pool), we have to
             // refine.
@@ -47,3 +42,19 @@ impl<'a> Search for BlockSearcher {
         }
     }
 }
+
+/// First-fit search.
+impl Search for block::Size {
+    fn refine(self, shortcut: &Shortcut) -> bool {
+        // We use the fat value to determine if we should refine. In particular, we know that the
+        // the node we're searching for (the first node above the given size or more) is skipped,
+        // if the fat value is bigger, since that by defintion means that it skips a block of at
+        // least that size.
+        shortcut.fat >= self
+    }
+
+    fn is_match(self, node: &Node) -> bool {
+        // A match is any block equal to or more than the target size.
+        node.block.size() >= self
+    }
+}