From cdf3b4e012dbc53bcadd19bd8e5a594a07511585 Mon Sep 17 00:00:00 2001 From: Nils Adermann Date: Sat, 19 May 2012 02:24:45 +0200 Subject: [PATCH] Use SplDoublyLinkedList instead of custom linked list --- .../DependencyResolver/RuleWatchChain.php | 34 ++++++ .../DependencyResolver/RuleWatchGraph.php | 105 ++++++------------ .../DependencyResolver/RuleWatchNode.php | 21 ++-- 3 files changed, 76 insertions(+), 84 deletions(-) create mode 100644 src/Composer/DependencyResolver/RuleWatchChain.php diff --git a/src/Composer/DependencyResolver/RuleWatchChain.php b/src/Composer/DependencyResolver/RuleWatchChain.php new file mode 100644 index 000000000..00ff0bc56 --- /dev/null +++ b/src/Composer/DependencyResolver/RuleWatchChain.php @@ -0,0 +1,34 @@ + + * Jordi Boggiano + * + * 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 + */ +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); + } +} diff --git a/src/Composer/DependencyResolver/RuleWatchGraph.php b/src/Composer/DependencyResolver/RuleWatchGraph.php index df736086e..2bc5cb7a3 100644 --- a/src/Composer/DependencyResolver/RuleWatchGraph.php +++ b/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; + foreach (array($node->watch1, $node->watch2) as $literal) { + if (!isset($this->watches[$literal])) { + $this->watches[$literal] = new RuleWatchChain; + } + + $this->watches[$literal]->unshift($node); } - - $node->next1 = $this->watches[$node->watch1]; - $this->watches[$node->watch1] = $node; - - if (!isset($this->watches[$node->watch2])) { - $this->watches[$node->watch2] = null; - } - - $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; - } + if (!$node->getRule()->isDisabled() && !call_user_func($skipCallback, $otherWatch)) { + $ruleLiterals = $node->getRule()->getLiterals(); - $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())) { + $this->moveWatch($literalId, $ruleLiteral->getId(), $node); - $node = $this->moveWatch($literalId, $ruleLiteral->getId(), $prevNode, $node, $nextNode); - - continue 2; + continue 2; + } } } + + if (call_user_func($conflictCallback, $otherWatch)) { + return $node->getRule(); + } + + call_user_func($decideCallback, $otherWatch, $level, $node->getRule()); } - // yay, we found a unit clause! try setting it to true - if (call_user_func($conflictCallback, $otherWatch)) { - return $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; + protected function moveWatch($fromLiteral, $toLiteral, $node) + { + if (!isset($this->watches[$toLiteral])) { + $this->watches[$toLiteral] = new RuleWatchChain; } - 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; - } - - $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); } } diff --git a/src/Composer/DependencyResolver/RuleWatchNode.php b/src/Composer/DependencyResolver/RuleWatchNode.php index c1589bdb0..037d14e3d 100644 --- a/src/Composer/DependencyResolver/RuleWatchNode.php +++ b/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,15 +61,6 @@ class RuleWatchNode return $this->rule; } - public function getNext($literalId) - { - if ($this->watch1 == $literalId) { - return $this->next1; - } else { - return $this->next2; - } - } - public function getOtherWatch($literalId) { if ($this->watch1 == $literalId) { @@ -81,4 +69,13 @@ class RuleWatchNode return $this->watch1; } } + + public function moveWatch($from, $to) + { + if ($this->watch1 == $from) { + $this->watch1 = $to; + } else { + $this->watch2 = $to; + } + } }