Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(906)

Unified Diff: sky/engine/platform/PODRedBlackTree.h

Issue 705373003: Remove PODIntervalTree and machinery. (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « sky/engine/platform/PODIntervalTreeTest.cpp ('k') | sky/engine/platform/PODRedBlackTreeTest.cpp » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: sky/engine/platform/PODRedBlackTree.h
diff --git a/sky/engine/platform/PODRedBlackTree.h b/sky/engine/platform/PODRedBlackTree.h
deleted file mode 100644
index 41ed7b97565fe12fe18cd94c70a1c6cd371d0c22..0000000000000000000000000000000000000000
--- a/sky/engine/platform/PODRedBlackTree.h
+++ /dev/null
@@ -1,828 +0,0 @@
-/*
- * Copyright (C) 2010 Google Inc. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-// A red-black tree, which is a form of a balanced binary tree. It
-// supports efficient insertion, deletion and queries of comparable
-// elements. The same element may be inserted multiple times. The
-// algorithmic complexity of common operations is:
-//
-// Insertion: O(lg(n))
-// Deletion: O(lg(n))
-// Querying: O(lg(n))
-//
-// The data type T that is stored in this red-black tree must be only
-// Plain Old Data (POD), or bottom out into POD. It must _not_ rely on
-// having its destructor called. This implementation internally
-// allocates storage in large chunks and does not call the destructor
-// on each object.
-//
-// Type T must supply a default constructor, a copy constructor, and
-// the "<" and "==" operators.
-//
-// In debug mode, printing of the data contained in the tree is
-// enabled. This requires the template specialization to be available:
-//
-// template<> struct ValueToString<T> {
-// static String string(const T& t);
-// };
-//
-// Note that when complex types are stored in this red/black tree, it
-// is possible that single invocations of the "<" and "==" operators
-// will be insufficient to describe the ordering of elements in the
-// tree during queries. As a concrete example, consider the case where
-// intervals are stored in the tree sorted by low endpoint. The "<"
-// operator on the Interval class only compares the low endpoint, but
-// the "==" operator takes into account the high endpoint as well.
-// This makes the necessary logic for querying and deletion somewhat
-// more complex. In order to properly handle such situations, the
-// property "needsFullOrderingComparisons" must be set to true on
-// the tree.
-//
-// This red-black tree is designed to be _augmented_; subclasses can
-// add additional and summary information to each node to efficiently
-// store and index more complex data structures. A concrete example is
-// the IntervalTree, which extends each node with a summary statistic
-// to efficiently store one-dimensional intervals.
-//
-// The design of this red-black tree comes from Cormen, Leiserson,
-// and Rivest, _Introduction to Algorithms_, MIT Press, 1990.
-
-#ifndef PODRedBlackTree_h
-#define PODRedBlackTree_h
-
-#include "platform/PODFreeListArena.h"
-#include "wtf/Assertions.h"
-#include "wtf/Noncopyable.h"
-#include "wtf/RefPtr.h"
-#ifndef NDEBUG
-#include "wtf/text/CString.h"
-#include "wtf/text/StringBuilder.h"
-#include "wtf/text/WTFString.h"
-#endif
-
-namespace blink {
-
-#ifndef NDEBUG
-template<class T>
-struct ValueToString;
-#endif
-
-enum UninitializedTreeEnum {
- UninitializedTree
-};
-
-template<class T>
-class PODRedBlackTree {
-public:
- class Node;
-
- // Visitor interface for walking all of the tree's elements.
- class Visitor {
- public:
- virtual void visit(const T& data) = 0;
- protected:
- virtual ~Visitor() { }
- };
-
- // Constructs a new red-black tree without allocating an arena.
- // isInitialized will return false in this case. initIfNeeded can be used
- // to init the structure. This constructor is usefull for creating
- // lazy initialized tree.
- explicit PODRedBlackTree(UninitializedTreeEnum)
- : m_root(0)
- , m_needsFullOrderingComparisons(false)
-#ifndef NDEBUG
- , m_verboseDebugging(false)
-#endif
- {
- }
-
- // Constructs a new red-black tree, allocating temporary objects
- // from a newly constructed PODFreeListArena.
- PODRedBlackTree()
- : m_arena(PODFreeListArena<Node>::create())
- , m_root(0)
- , m_needsFullOrderingComparisons(false)
-#ifndef NDEBUG
- , m_verboseDebugging(false)
-#endif
- {
- }
-
- // Constructs a new red-black tree, allocating temporary objects
- // from the given PODArena.
- explicit PODRedBlackTree(PassRefPtr<PODFreeListArena<Node> > arena)
- : m_arena(arena)
- , m_root(0)
- , m_needsFullOrderingComparisons(false)
-#ifndef NDEBUG
- , m_verboseDebugging(false)
-#endif
- {
- }
-
- virtual ~PODRedBlackTree() { }
-
- // Clearing will delete the contents of the tree. After this call
- // isInitialized will return false.
- void clear()
- {
- markFree(m_root);
- m_arena = nullptr;
- m_root = 0;
- }
-
- bool isInitialized() const
- {
- return m_arena;
- }
-
- void initIfNeeded()
- {
- if (!m_arena)
- m_arena = PODFreeListArena<Node>::create();
- }
-
- void initIfNeeded(PODFreeListArena<Node>* arena)
- {
- if (!m_arena)
- m_arena = arena;
- }
-
- void add(const T& data)
- {
- ASSERT(isInitialized());
- Node* node = m_arena->template allocateObject<T>(data);
- insertNode(node);
- }
-
- // Returns true if the datum was found in the tree.
- bool remove(const T& data)
- {
- ASSERT(isInitialized());
- Node* node = treeSearch(data);
- if (node) {
- deleteNode(node);
- return true;
- }
- return false;
- }
-
- bool contains(const T& data) const
- {
- ASSERT(isInitialized());
- return treeSearch(data);
- }
-
- void visitInorder(Visitor* visitor) const
- {
- ASSERT(isInitialized());
- if (!m_root)
- return;
- visitInorderImpl(m_root, visitor);
- }
-
- int size() const
- {
- ASSERT(isInitialized());
- Counter counter;
- visitInorder(&counter);
- return counter.count();
- }
-
- // See the class documentation for an explanation of this property.
- void setNeedsFullOrderingComparisons(bool needsFullOrderingComparisons)
- {
- m_needsFullOrderingComparisons = needsFullOrderingComparisons;
- }
-
- virtual bool checkInvariants() const
- {
- ASSERT(isInitialized());
- int blackCount;
- return checkInvariantsFromNode(m_root, &blackCount);
- }
-
-#ifndef NDEBUG
- // Dumps the tree's contents to the logging info stream for
- // debugging purposes.
- void dump() const
- {
- if (m_arena)
- dumpFromNode(m_root, 0);
- }
-
- // Turns on or off verbose debugging of the tree, causing many
- // messages to be logged during insertion and other operations in
- // debug mode.
- void setVerboseDebugging(bool verboseDebugging)
- {
- m_verboseDebugging = verboseDebugging;
- }
-#endif
-
- enum Color {
- Red = 1,
- Black
- };
-
- // The base Node class which is stored in the tree. Nodes are only
- // an internal concept; users of the tree deal only with the data
- // they store in it.
- class Node {
- WTF_MAKE_NONCOPYABLE(Node);
- public:
- // Constructor. Newly-created nodes are colored red.
- explicit Node(const T& data)
- : m_left(0)
- , m_right(0)
- , m_parent(0)
- , m_color(Red)
- , m_data(data)
- {
- }
-
- virtual ~Node() { }
-
- Color color() const { return m_color; }
- void setColor(Color color) { m_color = color; }
-
- // Fetches the user data.
- T& data() { return m_data; }
-
- // Copies all user-level fields from the source node, but not
- // internal fields. For example, the base implementation of this
- // method copies the "m_data" field, but not the child or parent
- // fields. Any augmentation information also does not need to be
- // copied, as it will be recomputed. Subclasses must call the
- // superclass implementation.
- virtual void copyFrom(Node* src) { m_data = src->data(); }
-
- Node* left() const { return m_left; }
- void setLeft(Node* node) { m_left = node; }
-
- Node* right() const { return m_right; }
- void setRight(Node* node) { m_right = node; }
-
- Node* parent() const { return m_parent; }
- void setParent(Node* node) { m_parent = node; }
-
- private:
- Node* m_left;
- Node* m_right;
- Node* m_parent;
- Color m_color;
- T m_data;
- };
-
-protected:
- // Returns the root of the tree, which is needed by some subclasses.
- Node* root() const { return m_root; }
-
-private:
- // This virtual method is the hook that subclasses should use when
- // augmenting the red-black tree with additional per-node summary
- // information. For example, in the case of an interval tree, this
- // is used to compute the maximum endpoint of the subtree below the
- // given node based on the values in the left and right children. It
- // is guaranteed that this will be called in the correct order to
- // properly update such summary information based only on the values
- // in the left and right children. This method should return true if
- // the node's summary information changed.
- virtual bool updateNode(Node*) { return false; }
-
- //----------------------------------------------------------------------
- // Generic binary search tree operations
- //
-
- // Searches the tree for the given datum.
- Node* treeSearch(const T& data) const
- {
- if (m_needsFullOrderingComparisons)
- return treeSearchFullComparisons(m_root, data);
-
- return treeSearchNormal(m_root, data);
- }
-
- // Searches the tree using the normal comparison operations,
- // suitable for simple data types such as numbers.
- Node* treeSearchNormal(Node* current, const T& data) const
- {
- while (current) {
- if (current->data() == data)
- return current;
- if (data < current->data())
- current = current->left();
- else
- current = current->right();
- }
- return 0;
- }
-
- // Searches the tree using multiple comparison operations, required
- // for data types with more complex behavior such as intervals.
- Node* treeSearchFullComparisons(Node* current, const T& data) const
- {
- if (!current)
- return 0;
- if (data < current->data())
- return treeSearchFullComparisons(current->left(), data);
- if (current->data() < data)
- return treeSearchFullComparisons(current->right(), data);
- if (data == current->data())
- return current;
-
- // We may need to traverse both the left and right subtrees.
- Node* result = treeSearchFullComparisons(current->left(), data);
- if (!result)
- result = treeSearchFullComparisons(current->right(), data);
- return result;
- }
-
- void treeInsert(Node* z)
- {
- Node* y = 0;
- Node* x = m_root;
- while (x) {
- y = x;
- if (z->data() < x->data())
- x = x->left();
- else
- x = x->right();
- }
- z->setParent(y);
- if (!y) {
- m_root = z;
- } else {
- if (z->data() < y->data())
- y->setLeft(z);
- else
- y->setRight(z);
- }
- }
-
- // Finds the node following the given one in sequential ordering of
- // their data, or null if none exists.
- Node* treeSuccessor(Node* x)
- {
- if (x->right())
- return treeMinimum(x->right());
- Node* y = x->parent();
- while (y && x == y->right()) {
- x = y;
- y = y->parent();
- }
- return y;
- }
-
- // Finds the minimum element in the sub-tree rooted at the given
- // node.
- Node* treeMinimum(Node* x)
- {
- while (x->left())
- x = x->left();
- return x;
- }
-
- // Helper for maintaining the augmented red-black tree.
- void propagateUpdates(Node* start)
- {
- bool shouldContinue = true;
- while (start && shouldContinue) {
- shouldContinue = updateNode(start);
- start = start->parent();
- }
- }
-
- //----------------------------------------------------------------------
- // Red-Black tree operations
- //
-
- // Left-rotates the subtree rooted at x.
- // Returns the new root of the subtree (x's right child).
- Node* leftRotate(Node* x)
- {
- // Set y.
- Node* y = x->right();
-
- // Turn y's left subtree into x's right subtree.
- x->setRight(y->left());
- if (y->left())
- y->left()->setParent(x);
-
- // Link x's parent to y.
- y->setParent(x->parent());
- if (!x->parent()) {
- m_root = y;
- } else {
- if (x == x->parent()->left())
- x->parent()->setLeft(y);
- else
- x->parent()->setRight(y);
- }
-
- // Put x on y's left.
- y->setLeft(x);
- x->setParent(y);
-
- // Update nodes lowest to highest.
- updateNode(x);
- updateNode(y);
- return y;
- }
-
- // Right-rotates the subtree rooted at y.
- // Returns the new root of the subtree (y's left child).
- Node* rightRotate(Node* y)
- {
- // Set x.
- Node* x = y->left();
-
- // Turn x's right subtree into y's left subtree.
- y->setLeft(x->right());
- if (x->right())
- x->right()->setParent(y);
-
- // Link y's parent to x.
- x->setParent(y->parent());
- if (!y->parent()) {
- m_root = x;
- } else {
- if (y == y->parent()->left())
- y->parent()->setLeft(x);
- else
- y->parent()->setRight(x);
- }
-
- // Put y on x's right.
- x->setRight(y);
- y->setParent(x);
-
- // Update nodes lowest to highest.
- updateNode(y);
- updateNode(x);
- return x;
- }
-
- // Inserts the given node into the tree.
- void insertNode(Node* x)
- {
- treeInsert(x);
- x->setColor(Red);
- updateNode(x);
-
- logIfVerbose(" PODRedBlackTree::InsertNode");
-
- // The node from which to start propagating updates upwards.
- Node* updateStart = x->parent();
-
- while (x != m_root && x->parent()->color() == Red) {
- if (x->parent() == x->parent()->parent()->left()) {
- Node* y = x->parent()->parent()->right();
- if (y && y->color() == Red) {
- // Case 1
- logIfVerbose(" Case 1/1");
- x->parent()->setColor(Black);
- y->setColor(Black);
- x->parent()->parent()->setColor(Red);
- updateNode(x->parent());
- x = x->parent()->parent();
- updateNode(x);
- updateStart = x->parent();
- } else {
- if (x == x->parent()->right()) {
- logIfVerbose(" Case 1/2");
- // Case 2
- x = x->parent();
- leftRotate(x);
- }
- // Case 3
- logIfVerbose(" Case 1/3");
- x->parent()->setColor(Black);
- x->parent()->parent()->setColor(Red);
- Node* newSubTreeRoot = rightRotate(x->parent()->parent());
- updateStart = newSubTreeRoot->parent();
- }
- } else {
- // Same as "then" clause with "right" and "left" exchanged.
- Node* y = x->parent()->parent()->left();
- if (y && y->color() == Red) {
- // Case 1
- logIfVerbose(" Case 2/1");
- x->parent()->setColor(Black);
- y->setColor(Black);
- x->parent()->parent()->setColor(Red);
- updateNode(x->parent());
- x = x->parent()->parent();
- updateNode(x);
- updateStart = x->parent();
- } else {
- if (x == x->parent()->left()) {
- // Case 2
- logIfVerbose(" Case 2/2");
- x = x->parent();
- rightRotate(x);
- }
- // Case 3
- logIfVerbose(" Case 2/3");
- x->parent()->setColor(Black);
- x->parent()->parent()->setColor(Red);
- Node* newSubTreeRoot = leftRotate(x->parent()->parent());
- updateStart = newSubTreeRoot->parent();
- }
- }
- }
-
- propagateUpdates(updateStart);
-
- m_root->setColor(Black);
- }
-
- // Restores the red-black property to the tree after splicing out
- // a node. Note that x may be null, which is why xParent must be
- // supplied.
- void deleteFixup(Node* x, Node* xParent)
- {
- while (x != m_root && (!x || x->color() == Black)) {
- if (x == xParent->left()) {
- // Note: the text points out that w can not be null.
- // The reason is not obvious from simply looking at
- // the code; it comes about from the properties of the
- // red-black tree.
- Node* w = xParent->right();
- ASSERT(w); // x's sibling should not be null.
- if (w->color() == Red) {
- // Case 1
- w->setColor(Black);
- xParent->setColor(Red);
- leftRotate(xParent);
- w = xParent->right();
- }
- if ((!w->left() || w->left()->color() == Black)
- && (!w->right() || w->right()->color() == Black)) {
- // Case 2
- w->setColor(Red);
- x = xParent;
- xParent = x->parent();
- } else {
- if (!w->right() || w->right()->color() == Black) {
- // Case 3
- w->left()->setColor(Black);
- w->setColor(Red);
- rightRotate(w);
- w = xParent->right();
- }
- // Case 4
- w->setColor(xParent->color());
- xParent->setColor(Black);
- if (w->right())
- w->right()->setColor(Black);
- leftRotate(xParent);
- x = m_root;
- xParent = x->parent();
- }
- } else {
- // Same as "then" clause with "right" and "left"
- // exchanged.
-
- // Note: the text points out that w can not be null.
- // The reason is not obvious from simply looking at
- // the code; it comes about from the properties of the
- // red-black tree.
- Node* w = xParent->left();
- ASSERT(w); // x's sibling should not be null.
- if (w->color() == Red) {
- // Case 1
- w->setColor(Black);
- xParent->setColor(Red);
- rightRotate(xParent);
- w = xParent->left();
- }
- if ((!w->right() || w->right()->color() == Black)
- && (!w->left() || w->left()->color() == Black)) {
- // Case 2
- w->setColor(Red);
- x = xParent;
- xParent = x->parent();
- } else {
- if (!w->left() || w->left()->color() == Black) {
- // Case 3
- w->right()->setColor(Black);
- w->setColor(Red);
- leftRotate(w);
- w = xParent->left();
- }
- // Case 4
- w->setColor(xParent->color());
- xParent->setColor(Black);
- if (w->left())
- w->left()->setColor(Black);
- rightRotate(xParent);
- x = m_root;
- xParent = x->parent();
- }
- }
- }
- if (x)
- x->setColor(Black);
- }
-
- // Deletes the given node from the tree. Note that this
- // particular node may not actually be removed from the tree;
- // instead, another node might be removed and its contents
- // copied into z.
- void deleteNode(Node* z)
- {
- // Y is the node to be unlinked from the tree.
- Node* y;
- if (!z->left() || !z->right())
- y = z;
- else
- y = treeSuccessor(z);
-
- // Y is guaranteed to be non-null at this point.
- Node* x;
- if (y->left())
- x = y->left();
- else
- x = y->right();
-
- // X is the child of y which might potentially replace y in
- // the tree. X might be null at this point.
- Node* xParent;
- if (x) {
- x->setParent(y->parent());
- xParent = x->parent();
- } else {
- xParent = y->parent();
- }
- if (!y->parent()) {
- m_root = x;
- } else {
- if (y == y->parent()->left())
- y->parent()->setLeft(x);
- else
- y->parent()->setRight(x);
- }
- if (y != z) {
- z->copyFrom(y);
- // This node has changed location in the tree and must be updated.
- updateNode(z);
- // The parent and its parents may now be out of date.
- propagateUpdates(z->parent());
- }
-
- // If we haven't already updated starting from xParent, do so now.
- if (xParent && xParent != y && xParent != z)
- propagateUpdates(xParent);
- if (y->color() == Black)
- deleteFixup(x, xParent);
-
- m_arena->freeObject(y);
- }
-
- // Visits the subtree rooted at the given node in order.
- void visitInorderImpl(Node* node, Visitor* visitor) const
- {
- if (node->left())
- visitInorderImpl(node->left(), visitor);
- visitor->visit(node->data());
- if (node->right())
- visitInorderImpl(node->right(), visitor);
- }
-
- void markFree(Node *node)
- {
- if (!node)
- return;
-
- if (node->left())
- markFree(node->left());
- if (node->right())
- markFree(node->right());
- m_arena->freeObject(node);
- }
-
- //----------------------------------------------------------------------
- // Helper class for size()
-
- // A Visitor which simply counts the number of visited elements.
- class Counter : public Visitor {
- WTF_MAKE_NONCOPYABLE(Counter);
- public:
- Counter()
- : m_count(0) { }
-
- virtual void visit(const T&) { ++m_count; }
- int count() const { return m_count; }
-
- private:
- int m_count;
- };
-
- //----------------------------------------------------------------------
- // Verification and debugging routines
- //
-
- // Returns in the "blackCount" parameter the number of black
- // children along all paths to all leaves of the given node.
- bool checkInvariantsFromNode(Node* node, int* blackCount) const
- {
- // Base case is a leaf node.
- if (!node) {
- *blackCount = 1;
- return true;
- }
-
- // Each node is either red or black.
- if (!(node->color() == Red || node->color() == Black))
- return false;
-
- // Every leaf (or null) is black.
-
- if (node->color() == Red) {
- // Both of its children are black.
- if (!((!node->left() || node->left()->color() == Black)))
- return false;
- if (!((!node->right() || node->right()->color() == Black)))
- return false;
- }
-
- // Every simple path to a leaf node contains the same number of
- // black nodes.
- int leftCount = 0, rightCount = 0;
- bool leftValid = checkInvariantsFromNode(node->left(), &leftCount);
- bool rightValid = checkInvariantsFromNode(node->right(), &rightCount);
- if (!leftValid || !rightValid)
- return false;
- *blackCount = leftCount + (node->color() == Black ? 1 : 0);
- return leftCount == rightCount;
- }
-
-#ifdef NDEBUG
- void logIfVerbose(const char*) const { }
-#else
- void logIfVerbose(const char* output) const
- {
- if (m_verboseDebugging)
- WTF_LOG_ERROR("%s", output);
- }
-#endif
-
-#ifndef NDEBUG
- // Dumps the subtree rooted at the given node.
- void dumpFromNode(Node* node, int indentation) const
- {
- StringBuilder builder;
- for (int i = 0; i < indentation; i++)
- builder.append(' ');
- builder.append('-');
- if (node) {
- builder.append(' ');
- builder.append(ValueToString<T>::string(node->data()));
- builder.append((node->color() == Black) ? " (black)" : " (red)");
- }
- WTF_LOG_ERROR("%s", builder.toString().ascii().data());
- if (node) {
- dumpFromNode(node->left(), indentation + 2);
- dumpFromNode(node->right(), indentation + 2);
- }
- }
-#endif
-
- //----------------------------------------------------------------------
- // Data members
-
- RefPtr<PODFreeListArena<Node> > m_arena;
- Node* m_root;
- bool m_needsFullOrderingComparisons;
-#ifndef NDEBUG
- bool m_verboseDebugging;
-#endif
-};
-
-} // namespace blink
-
-#endif // PODRedBlackTree_h
« no previous file with comments | « sky/engine/platform/PODIntervalTreeTest.cpp ('k') | sky/engine/platform/PODRedBlackTreeTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698