Browse Source

Use SplDoublyLinkedList instead of custom linked list

Nils Adermann 13 years ago
parent
commit
cdf3b4e012

+ 34 - 0
src/Composer/DependencyResolver/RuleWatchChain.php

@@ -0,0 +1,34 @@
+<?php
+
+/*
+ * This file is part of Composer.
+ *
+ * (c) Nils Adermann <naderman@naderman.de>
+ *     Jordi Boggiano <j.boggiano@seld.be>
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Composer\DependencyResolver;
+
+/**
+ * @author Nils Adermann <naderman@naderman.de>
+ */
+class RuleWatchChain extends \SplDoublyLinkedList
+{
+    protected $offset = 0;
+
+    public function seek($offset)
+    {
+        $this->rewind();
+        for ($i = 0; $i < $offset; $i++, $this->next());
+    }
+
+    public function remove()
+    {
+        $offset = $this->key();
+        $this->offsetUnset($offset);
+        $this->seek($offset);
+    }
+}

+ 31 - 70
src/Composer/DependencyResolver/RuleWatchGraph.php

@@ -22,30 +22,20 @@ class RuleWatchGraph
     /**
      * Alters watch chains for a rule.
      *
-     * Next1/2 always points to the next rule that is watching the same package.
-     * The watches array contains rules to start from for each package
-     *
      */
     public function insert(RuleWatchNode $node)
     {
-        // skip simple assertions of the form (A) or (-A)
         if ($node->getRule()->isAssertion()) {
             return;
         }
 
-        if (!isset($this->watches[$node->watch1])) {
-            $this->watches[$node->watch1] = null;
-        }
-
-        $node->next1 = $this->watches[$node->watch1];
-        $this->watches[$node->watch1] = $node;
+        foreach (array($node->watch1, $node->watch2) as $literal) {
+            if (!isset($this->watches[$literal])) {
+                $this->watches[$literal] = new RuleWatchChain;
+            }
 
-        if (!isset($this->watches[$node->watch2])) {
-            $this->watches[$node->watch2] = null;
+            $this->watches[$literal]->unshift($node);
         }
-
-        $node->next2 = $this->watches[$node->watch2];
-        $this->watches[$node->watch2] = $node;
     }
 
     public function contains($literalId)
@@ -56,79 +46,50 @@ class RuleWatchGraph
     public function walkLiteral($literalId, $level, $skipCallback, $conflictCallback, $decideCallback)
     {
         if (!isset($this->watches[$literalId])) {
-            return;
+            return null;
         }
 
-        $prevNode = null;
-        for ($node = $this->watches[$literalId]; $node !== null; $prevNode = $node, $node = $nextNode) {
-            $nextNode = $node->getNext($literalId);
-
-            if ($node->getRule()->isDisabled()) {
-                continue;
-            }
-
+        $this->watches[$literalId]->rewind();
+        while ($this->watches[$literalId]->valid()) {
+            $node = $this->watches[$literalId]->current();
             $otherWatch = $node->getOtherWatch($literalId);
 
-            if (call_user_func($skipCallback, $otherWatch)) {
-                continue;
-            }
-
-            $ruleLiterals = $node->getRule()->getLiterals();
+            if (!$node->getRule()->isDisabled() && !call_user_func($skipCallback, $otherWatch)) {
+                $ruleLiterals = $node->getRule()->getLiterals();
 
-            if (sizeof($ruleLiterals) > 2) {
-                foreach ($ruleLiterals as $ruleLiteral) {
-                    if ($otherWatch !== $ruleLiteral->getId() &&
-                        !call_user_func($conflictCallback, $ruleLiteral->getId())) {
+                if (sizeof($ruleLiterals) > 2) {
+                    foreach ($ruleLiterals as $ruleLiteral) {
+                        if ($otherWatch !== $ruleLiteral->getId() &&
+                            !call_user_func($conflictCallback, $ruleLiteral->getId())) {
 
-                        $node = $this->moveWatch($literalId, $ruleLiteral->getId(), $prevNode, $node, $nextNode);
+                            $this->moveWatch($literalId, $ruleLiteral->getId(), $node);
 
-                        continue 2;
+                            continue 2;
+                        }
                     }
                 }
-            }
 
-            // yay, we found a unit clause! try setting it to true
-            if (call_user_func($conflictCallback, $otherWatch)) {
-                return $node->getRule();
+                if (call_user_func($conflictCallback, $otherWatch)) {
+                    return $node->getRule();
+                }
+
+                call_user_func($decideCallback, $otherWatch, $level, $node->getRule());
             }
 
-            call_user_func($decideCallback, $otherWatch, $level, $node->getRule());
+            $this->watches[$literalId]->next();
         }
 
         return null;
     }
 
-    public function moveWatch($fromLiteral, $toLiteral, $prevNode, $node, $nextNode) {
-        if ($fromLiteral == $node->watch1) {
-            $node->watch1 = $toLiteral;
-            $node->next1 = (isset($this->watches[$toLiteral])) ? $this->watches[$toLiteral] : null;
-        } else {
-            $node->watch2 = $toLiteral;
-            $node->next2 = (isset($this->watches[$toLiteral])) ? $this->watches[$toLiteral] : null;
-        }
-
-        if ($prevNode) {
-            if ($prevNode->next1 === $node) {
-                $prevNode->next1 = $nextNode;
-            } else {
-                $prevNode->next2 = $nextNode;
-            }
-        } else {
-            $this->watches[$fromLiteral] = $nextNode;
-        }
-
-        $this->watches[$toLiteral] = $node;
-
-        if ($prevNode) {
-            return $prevNode;
+    protected function moveWatch($fromLiteral, $toLiteral, $node)
+    {
+        if (!isset($this->watches[$toLiteral])) {
+            $this->watches[$toLiteral] = new RuleWatchChain;
         }
 
-        $tmpNode = new RuleWatchNode(new Rule(array(), null, null));
-        $tmpNode->watch1 = $fromLiteral;
-        $tmpNode->next1 = $nextNode;
-        $tmpNode->watch2 = $fromLiteral;
-        $tmpNode->next2 = $nextNode;
-
-        return $tmpNode;
+        $node->moveWatch($fromLiteral, $toLiteral);
+        $this->watches[$fromLiteral]->remove();
+        $this->watches[$toLiteral]->unshift($node);
     }
 }

+ 7 - 10
src/Composer/DependencyResolver/RuleWatchNode.php

@@ -22,9 +22,6 @@ class RuleWatchNode
     public $watch1;
     public $watch2;
 
-    public $next1;
-    public $next2;
-
     public function __construct($rule)
     {
         $this->rule = $rule;
@@ -64,21 +61,21 @@ class RuleWatchNode
         return $this->rule;
     }
 
-    public function getNext($literalId)
+    public function getOtherWatch($literalId)
     {
         if ($this->watch1 == $literalId) {
-            return $this->next1;
+            return $this->watch2;
         } else {
-            return $this->next2;
+            return $this->watch1;
         }
     }
 
-    public function getOtherWatch($literalId)
+    public function moveWatch($from, $to)
     {
-        if ($this->watch1 == $literalId) {
-            return $this->watch2;
+        if ($this->watch1 == $from) {
+            $this->watch1 = $to;
         } else {
-            return $this->watch1;
+            $this->watch2 = $to;
         }
     }
 }