memory/build/rb.h
author Mike Hommey <mh+mozilla@glandium.org>
Wed, 27 Sep 2017 13:50:50 +0900
changeset 670936 c21e81f77ae1b167d9db5435bbd75ba30572c81e
parent 670935 2154d015f9f9cae085465dcf2e3e2c709a521ce6
child 670937 8662255eb3de7f8fb54f5d7c8dc3281881c437c5
child 670938 45e6d757ef72f59b9ee9294183b4cc8ad445e48f
permissions -rw-r--r--
Bug 1403444 - Remove rbp_f_synced. r?njn Bug 1365460 removed the macros that used it.

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

/*
 * Portions of this file were originally under the following license:
 *
 * Copyright (C) 2008 Jason Evans <jasone@FreeBSD.org>.
 * 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(s), this list of conditions and the following disclaimer
 *    unmodified other than the allowable addition of one or more
 *    copyright notices.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice(s), this list of conditions and the following disclaimer in
 *    the documentation and/or other materials provided with the
 *    distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``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 THE COPYRIGHT HOLDER(S) 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.
 *
 ******************************************************************************
 *
 * C++ template implementation of left-leaning red-black trees.
 *
 * Usage:
 *
 *   #define SIZEOF_PTR ...
 *   #define SIZEOF_PTR_2POW ...
 *
 *   #include <rb.h>
 *   ...
 *
 * All operations are done non-recursively.  Parent pointers are not used, and
 * color bits are stored in the least significant bit of right-child pointers,
 * thus making node linkage as compact as is possible for red-black trees.
 *
 * The RedBlackTree template expects two type arguments: the type of the nodes,
 * containing a RedBlackTreeNode, and a trait providing two methods:
 *  - a GetTreeNode method that returns a reference to the RedBlackTreeNode
 *    corresponding to a given node with the following signature:
 *      static RedBlackTreeNode<T>& GetTreeNode(T*)
 *  - a Compare function with the following signature:
 *      static int Compare(T* aNode, T* aOther)
 *                            ^^^^^
 *                         or aKey
 *
 * Interpretation of comparision function return values:
 *
 *   -1 : aNode <  aOther
 *    0 : aNode == aOther
 *    1 : aNode >  aOther
 *
 * In all cases, the aNode or aKey argument is the first argument to the
 * comparison function, which makes it possible to write comparison functions
 * that treat the first argument specially.
 *
 ******************************************************************************/

#ifndef RB_H_
#define RB_H_

enum NodeColor
{
  Black = 0,
  Red = 1,
};

/* Node structure. */
template <typename T>
class RedBlackTreeNode
{
  uintptr_t mLeft;
  uintptr_t mRightAndColor;

public:
  T* Left()
  {
    return reinterpret_cast<T*>(mLeft);
  }

  void SetLeft(T* aValue)
  {
    mLeft = reinterpret_cast<uintptr_t>(aValue);
  }

  T* Right()
  {
    return reinterpret_cast<T*>(mRightAndColor & uintptr_t(~1));
  }

  void SetRight(T* aValue)
  {
    mRightAndColor = (reinterpret_cast<uintptr_t>(aValue) & uintptr_t(~1)) | Color();
  }

  NodeColor Color()
  {
    return static_cast<NodeColor>(mRightAndColor & 1);
  }

  bool IsBlack()
  {
    return Color() == NodeColor::Black;
  }

  bool IsRed()
  {
    return Color() == NodeColor::Red;
  }

  void SetColor(NodeColor aColor)
  {
    mRightAndColor = (mRightAndColor & uintptr_t(~1)) | aColor;
  }
};

/* Tree structure. */
template<typename T, typename Trait>
struct RedBlackTree
{
  T* rbt_root;
  T rbt_nil;

  void Init()
  {
    rbt_root = &rbt_nil;
    Trait::GetTreeNode(&rbt_nil).SetLeft(&rbt_nil);
    Trait::GetTreeNode(&rbt_nil).SetRight(&rbt_nil);
    Trait::GetTreeNode(&rbt_nil).SetColor(NodeColor::Black);
  }

  T* First(T* aStart = nullptr)
  {
    T* ret;
    for (ret = aStart ? aStart : rbt_root;
         Trait::GetTreeNode(ret).Left() != &rbt_nil;
         ret = Trait::GetTreeNode(ret).Left()) {
    }
    return (ret == &rbt_nil) ? nullptr : ret;
  }

  T* Last(T* aStart = nullptr)
  {
    T* ret;
    for (ret = aStart ? aStart : rbt_root;
         Trait::GetTreeNode(ret).Right() != &rbt_nil;
         ret = Trait::GetTreeNode(ret).Right()) {
    }
    return (ret == &rbt_nil) ? nullptr : ret;
  }

  T* Next(T* aNode)
  {
    T* ret;
    if (Trait::GetTreeNode(aNode).Right() != &rbt_nil) {
      ret = First(Trait::GetTreeNode(aNode).Right());
    } else {
      T* rbp_n_t = rbt_root;
      MOZ_ASSERT(rbp_n_t != &rbt_nil);
      ret = &rbt_nil;
      while (true) {
        int rbp_n_cmp = Trait::Compare(aNode, rbp_n_t);
        if (rbp_n_cmp < 0) {
          ret = rbp_n_t;
          rbp_n_t = Trait::GetTreeNode(rbp_n_t).Left();
        } else if (rbp_n_cmp > 0) {
          rbp_n_t = Trait::GetTreeNode(rbp_n_t).Right();
        } else {
          break;
        }
        MOZ_ASSERT(rbp_n_t != &rbt_nil);
      }
    }
    return (ret == &rbt_nil) ? nullptr : ret;
  }

  T* Prev(T* aNode)
  {
    T* ret;
    if (Trait::GetTreeNode(aNode).Left() != &rbt_nil) {
      ret = Last(Trait::GetTreeNode(aNode).Left());
    } else {
      T* rbp_p_t = rbt_root;
      MOZ_ASSERT(rbp_p_t != &rbt_nil);
      ret = &rbt_nil;
      while (true) {
        int rbp_p_cmp = Trait::Compare(aNode, rbp_p_t);
        if (rbp_p_cmp < 0) {
          rbp_p_t = Trait::GetTreeNode(rbp_p_t).Left();
        } else if (rbp_p_cmp > 0) {
          ret = rbp_p_t;
          rbp_p_t = Trait::GetTreeNode(rbp_p_t).Right();
        } else {
          break;
        }
        MOZ_ASSERT(rbp_p_t != &rbt_nil);
      }
    }
    return (ret == &rbt_nil) ? nullptr : ret;
  }

  T* Search(T* aKey)
  {
    T* ret = rbt_root;
    int rbp_se_cmp;
    while (ret != &rbt_nil && (rbp_se_cmp = Trait::Compare(aKey, ret)) != 0) {
      if (rbp_se_cmp < 0) {
        ret = Trait::GetTreeNode(ret).Left();
      } else {
        ret = Trait::GetTreeNode(ret).Right();
      }
    }
    return (ret == &rbt_nil) ? nullptr : ret;
  }

  /* Find a match if it exists. Otherwise, find the next greater node, if one
   * exists */
  T* SearchOrNext(T* aKey)
  {
    T* ret = nullptr;
    T* rbp_ns_t = rbt_root;
    while (rbp_ns_t != &rbt_nil) {
      int rbp_ns_cmp = Trait::Compare(aKey, rbp_ns_t);
      if (rbp_ns_cmp < 0) {
        ret = rbp_ns_t;
        rbp_ns_t = Trait::GetTreeNode(rbp_ns_t).Left();
      } else if (rbp_ns_cmp > 0) {
        rbp_ns_t = Trait::GetTreeNode(rbp_ns_t).Right();
      } else {
        ret = rbp_ns_t;
        break;
      }
    }
    return ret;
  }

  void Insert(T* aNode)
  {
    T rbp_i_s;
    T *rbp_i_g, *rbp_i_p, *rbp_i_c, *rbp_i_t, *rbp_i_u;
    int rbp_i_cmp = 0;
    rbp_i_g = &rbt_nil;
    Trait::GetTreeNode(&rbp_i_s).SetLeft(rbt_root);
    Trait::GetTreeNode(&rbp_i_s).SetRight(&rbt_nil);
    Trait::GetTreeNode(&rbp_i_s).SetColor(NodeColor::Black);
    rbp_i_p = &rbp_i_s;
    rbp_i_c = rbt_root;
    /* Iteratively search down the tree for the insertion point,
     * splitting 4-nodes as they are encountered. At the end of each
     * iteration, rbp_i_g->rbp_i_p->rbp_i_c is a 3-level path down
     * the tree, assuming a sufficiently deep tree. */
    while (rbp_i_c != &rbt_nil) {
      rbp_i_t = Trait::GetTreeNode(rbp_i_c).Left();
      rbp_i_u = Trait::GetTreeNode(rbp_i_t).Left();
      if (Trait::GetTreeNode(rbp_i_t).IsRed() &&
          Trait::GetTreeNode(rbp_i_u).IsRed()) {
        /* rbp_i_c is the top of a logical 4-node, so split it.
         * This iteration does not move down the tree, due to the
         * disruptiveness of node splitting.
         *
         * Rotate right. */
        rbp_i_t = RotateRight(rbp_i_c);
        /* Pass red links up one level. */
        rbp_i_u = Trait::GetTreeNode(rbp_i_t).Left();
        Trait::GetTreeNode(rbp_i_u).SetColor(NodeColor::Black);
        if (Trait::GetTreeNode(rbp_i_p).Left() == rbp_i_c) {
          Trait::GetTreeNode(rbp_i_p).SetLeft(rbp_i_t);
          rbp_i_c = rbp_i_t;
        } else {
          /* rbp_i_c was the right child of rbp_i_p, so rotate
           * left in order to maintain the left-leaning invariant. */
          MOZ_ASSERT(Trait::GetTreeNode(rbp_i_p).Right() == rbp_i_c);
          Trait::GetTreeNode(rbp_i_p).SetRight(rbp_i_t);
          rbp_i_u = LeanLeft(rbp_i_p);
          if (Trait::GetTreeNode(rbp_i_g).Left() == rbp_i_p) {
            Trait::GetTreeNode(rbp_i_g).SetLeft(rbp_i_u);
          } else {
            MOZ_ASSERT(Trait::GetTreeNode(rbp_i_g).Right() == rbp_i_p);
            Trait::GetTreeNode(rbp_i_g).SetRight(rbp_i_u);
          }
          rbp_i_p = rbp_i_u;
          rbp_i_cmp = Trait::Compare(aNode, rbp_i_p);
          if (rbp_i_cmp < 0) {
            rbp_i_c = Trait::GetTreeNode(rbp_i_p).Left();
          } else {
            MOZ_ASSERT(rbp_i_cmp > 0);
            rbp_i_c = Trait::GetTreeNode(rbp_i_p).Right();
          }
          continue;
        }
      }
      rbp_i_g = rbp_i_p;
      rbp_i_p = rbp_i_c;
      rbp_i_cmp = Trait::Compare(aNode, rbp_i_c);
      if (rbp_i_cmp < 0) {
        rbp_i_c = Trait::GetTreeNode(rbp_i_c).Left();
      } else {
        MOZ_ASSERT(rbp_i_cmp > 0);
        rbp_i_c = Trait::GetTreeNode(rbp_i_c).Right();
      }
    }
    /* rbp_i_p now refers to the node under which to insert. */
    Trait::GetTreeNode(aNode).SetLeft(&rbt_nil);
    Trait::GetTreeNode(aNode).SetRight(&rbt_nil);
    Trait::GetTreeNode(aNode).SetColor(NodeColor::Red);
    if (rbp_i_cmp > 0) {
      Trait::GetTreeNode(rbp_i_p).SetRight(aNode);
      rbp_i_t = LeanLeft(rbp_i_p);
      if (Trait::GetTreeNode(rbp_i_g).Left() == rbp_i_p) {
        Trait::GetTreeNode(rbp_i_g).SetLeft(rbp_i_t);
      } else if (Trait::GetTreeNode(rbp_i_g).Right() == rbp_i_p) {
        Trait::GetTreeNode(rbp_i_g).SetRight(rbp_i_t);
      }
    } else {
      Trait::GetTreeNode(rbp_i_p).SetLeft(aNode);
    }
    /* Update the root and make sure that it is black. */
    rbt_root = Trait::GetTreeNode(&rbp_i_s).Left();
    Trait::GetTreeNode(rbt_root).SetColor(NodeColor::Black);
  }

  void Remove(T* aNode)
  {
    T rbp_r_s;
    T *rbp_r_p, *rbp_r_c, *rbp_r_xp, *rbp_r_t, *rbp_r_u;
    int rbp_r_cmp;
    Trait::GetTreeNode(&rbp_r_s).SetLeft(rbt_root);
    Trait::GetTreeNode(&rbp_r_s).SetRight(&rbt_nil);
    Trait::GetTreeNode(&rbp_r_s).SetColor(NodeColor::Black);
    rbp_r_p = &rbp_r_s;
    rbp_r_c = rbt_root;
    rbp_r_xp = &rbt_nil;
    /* Iterate down the tree, but always transform 2-nodes to 3- or
     * 4-nodes in order to maintain the invariant that the current
     * node is not a 2-node. This allows simple deletion once a leaf
     * is reached. Handle the root specially though, since there may
     * be no way to convert it from a 2-node to a 3-node. */
    rbp_r_cmp = Trait::Compare(aNode, rbp_r_c);
    if (rbp_r_cmp < 0) {
      rbp_r_t = Trait::GetTreeNode(rbp_r_c).Left();
      rbp_r_u = Trait::GetTreeNode(rbp_r_t).Left();
      if (Trait::GetTreeNode(rbp_r_t).IsBlack() &&
          Trait::GetTreeNode(rbp_r_u).IsBlack()) {
        /* Apply standard transform to prepare for left move. */
        rbp_r_t = MoveRedLeft(rbp_r_c);
        Trait::GetTreeNode(rbp_r_t).SetColor(NodeColor::Black);
        Trait::GetTreeNode(rbp_r_p).SetLeft(rbp_r_t);
        rbp_r_c = rbp_r_t;
      } else {
        /* Move left. */
        rbp_r_p = rbp_r_c;
        rbp_r_c = Trait::GetTreeNode(rbp_r_c).Left();
      }
    } else {
      if (rbp_r_cmp == 0) {
        MOZ_ASSERT(aNode == rbp_r_c);
        if (Trait::GetTreeNode(rbp_r_c).Right() == &rbt_nil) {
          /* Delete root node (which is also a leaf node). */
          if (Trait::GetTreeNode(rbp_r_c).Left() != &rbt_nil) {
            rbp_r_t = LeanRight(rbp_r_c);
            Trait::GetTreeNode(rbp_r_t).SetRight(&rbt_nil);
          } else {
            rbp_r_t = &rbt_nil;
          }
          Trait::GetTreeNode(rbp_r_p).SetLeft(rbp_r_t);
        } else {
          /* This is the node we want to delete, but we will
           * instead swap it with its successor and delete the
           * successor. Record enough information to do the
           * swap later. rbp_r_xp is the aNode's parent. */
          rbp_r_xp = rbp_r_p;
          rbp_r_cmp = 1; /* Note that deletion is incomplete. */
        }
      }
      if (rbp_r_cmp == 1) {
        if (Trait::GetTreeNode(
              Trait::GetTreeNode(Trait::GetTreeNode(rbp_r_c).Right()).Left())
              .IsBlack()) {
          rbp_r_t = Trait::GetTreeNode(rbp_r_c).Left();
          if (Trait::GetTreeNode(rbp_r_t).IsRed()) {
            /* Standard transform. */
            rbp_r_t = MoveRedRight(rbp_r_c);
          } else {
            /* Root-specific transform. */
            Trait::GetTreeNode(rbp_r_c).SetColor(NodeColor::Red);
            rbp_r_u = Trait::GetTreeNode(rbp_r_t).Left();
            if (Trait::GetTreeNode(rbp_r_u).IsRed()) {
              Trait::GetTreeNode(rbp_r_u).SetColor(NodeColor::Black);
              rbp_r_t = RotateRight(rbp_r_c);
              rbp_r_u = RotateLeft(rbp_r_c);
              Trait::GetTreeNode(rbp_r_t).SetRight(rbp_r_u);
            } else {
              Trait::GetTreeNode(rbp_r_t).SetColor(NodeColor::Red);
              rbp_r_t = RotateLeft(rbp_r_c);
            }
          }
          Trait::GetTreeNode(rbp_r_p).SetLeft(rbp_r_t);
          rbp_r_c = rbp_r_t;
        } else {
          /* Move right. */
          rbp_r_p = rbp_r_c;
          rbp_r_c = Trait::GetTreeNode(rbp_r_c).Right();
        }
      }
    }
    if (rbp_r_cmp != 0) {
      while (true) {
        MOZ_ASSERT(rbp_r_p != &rbt_nil);
        rbp_r_cmp = Trait::Compare(aNode, rbp_r_c);
        if (rbp_r_cmp < 0) {
          rbp_r_t = Trait::GetTreeNode(rbp_r_c).Left();
          if (rbp_r_t == &rbt_nil) {
            /* rbp_r_c now refers to the successor node to
             * relocate, and rbp_r_xp/aNode refer to the
             * context for the relocation. */
            if (Trait::GetTreeNode(rbp_r_xp).Left() == (aNode)) {
              Trait::GetTreeNode(rbp_r_xp).SetLeft(rbp_r_c);
            } else {
              MOZ_ASSERT(Trait::GetTreeNode(rbp_r_xp).Right() == (aNode));
              Trait::GetTreeNode(rbp_r_xp).SetRight(rbp_r_c);
            }
            Trait::GetTreeNode(rbp_r_c).SetLeft(
              Trait::GetTreeNode(aNode).Left());
            Trait::GetTreeNode(rbp_r_c).SetRight(
              Trait::GetTreeNode(aNode).Right());
            Trait::GetTreeNode(rbp_r_c).SetColor(
              Trait::GetTreeNode(aNode).Color());
            if (Trait::GetTreeNode(rbp_r_p).Left() == rbp_r_c) {
              Trait::GetTreeNode(rbp_r_p).SetLeft(&rbt_nil);
            } else {
              MOZ_ASSERT(Trait::GetTreeNode(rbp_r_p).Right() == rbp_r_c);
              Trait::GetTreeNode(rbp_r_p).SetRight(&rbt_nil);
            }
            break;
          }
          rbp_r_u = Trait::GetTreeNode(rbp_r_t).Left();
          if (Trait::GetTreeNode(rbp_r_t).IsBlack() &&
              Trait::GetTreeNode(rbp_r_u).IsBlack()) {
            rbp_r_t = MoveRedLeft(rbp_r_c);
            if (Trait::GetTreeNode(rbp_r_p).Left() == rbp_r_c) {
              Trait::GetTreeNode(rbp_r_p).SetLeft(rbp_r_t);
            } else {
              Trait::GetTreeNode(rbp_r_p).SetRight(rbp_r_t);
            }
            rbp_r_c = rbp_r_t;
          } else {
            rbp_r_p = rbp_r_c;
            rbp_r_c = Trait::GetTreeNode(rbp_r_c).Left();
          }
        } else {
          /* Check whether to delete this node (it has to be
           * the correct node and a leaf node). */
          if (rbp_r_cmp == 0) {
            MOZ_ASSERT(aNode == rbp_r_c);
            if (Trait::GetTreeNode(rbp_r_c).Right() == &rbt_nil) {
              /* Delete leaf node. */
              if (Trait::GetTreeNode(rbp_r_c).Left() != &rbt_nil) {
                rbp_r_t = LeanRight(rbp_r_c);
                Trait::GetTreeNode(rbp_r_t).SetRight(&rbt_nil);
              } else {
                rbp_r_t = &rbt_nil;
              }
              if (Trait::GetTreeNode(rbp_r_p).Left() == rbp_r_c) {
                Trait::GetTreeNode(rbp_r_p).SetLeft(rbp_r_t);
              } else {
                Trait::GetTreeNode(rbp_r_p).SetRight(rbp_r_t);
              }
              break;
            } else {
              /* This is the node we want to delete, but we
               * will instead swap it with its successor
               * and delete the successor. Record enough
               * information to do the swap later.
               * rbp_r_xp is aNode's parent. */
              rbp_r_xp = rbp_r_p;
            }
          }
          rbp_r_t = Trait::GetTreeNode(rbp_r_c).Right();
          rbp_r_u = Trait::GetTreeNode(rbp_r_t).Left();
          if (Trait::GetTreeNode(rbp_r_u).IsBlack()) {
            rbp_r_t = MoveRedRight(rbp_r_c);
            if (Trait::GetTreeNode(rbp_r_p).Left() == rbp_r_c) {
              Trait::GetTreeNode(rbp_r_p).SetLeft(rbp_r_t);
            } else {
              Trait::GetTreeNode(rbp_r_p).SetRight(rbp_r_t);
            }
            rbp_r_c = rbp_r_t;
          } else {
            rbp_r_p = rbp_r_c;
            rbp_r_c = Trait::GetTreeNode(rbp_r_c).Right();
          }
        }
      }
    }
    /* Update root. */
    rbt_root = Trait::GetTreeNode(&rbp_r_s).Left();
  }

private:
  T* RotateLeft(T* aNode)
  {
    T* node = Trait::GetTreeNode(aNode).Right();
    Trait::GetTreeNode(aNode).SetRight(Trait::GetTreeNode(node).Left());
    Trait::GetTreeNode(node).SetLeft(aNode);
    return node;
  }

  T* RotateRight(T* aNode)
  {
    T* node = Trait::GetTreeNode(aNode).Left();
    Trait::GetTreeNode(aNode).SetLeft(Trait::GetTreeNode(node).Right());
    Trait::GetTreeNode(node).SetRight(aNode);
    return node;
  }

  T* LeanLeft(T* aNode)
  {
    T* node = RotateLeft(aNode);
    NodeColor color = Trait::GetTreeNode(aNode).Color();
    Trait::GetTreeNode(node).SetColor(color);
    Trait::GetTreeNode(aNode).SetColor(NodeColor::Red);
    return node;
  }

  T* LeanRight(T* aNode)
  {
    T* node = RotateRight(aNode);
    NodeColor color = Trait::GetTreeNode(aNode).Color();
    Trait::GetTreeNode(node).SetColor(color);
    Trait::GetTreeNode(aNode).SetColor(NodeColor::Red);
    return node;
  }

  T* MoveRedLeft(T* aNode)
  {
    T* node;
    T *rbp_mrl_t, *rbp_mrl_u;
    rbp_mrl_t = Trait::GetTreeNode(aNode).Left();
    Trait::GetTreeNode(rbp_mrl_t).SetColor(NodeColor::Red);
    rbp_mrl_t = Trait::GetTreeNode(aNode).Right();
    rbp_mrl_u = Trait::GetTreeNode(rbp_mrl_t).Left();
    if (Trait::GetTreeNode(rbp_mrl_u).IsRed()) {
      rbp_mrl_u = RotateRight(rbp_mrl_t);
      Trait::GetTreeNode(aNode).SetRight(rbp_mrl_u);
      node = RotateLeft(aNode);
      rbp_mrl_t = Trait::GetTreeNode(aNode).Right();
      if (Trait::GetTreeNode(rbp_mrl_t).IsRed()) {
        Trait::GetTreeNode(rbp_mrl_t).SetColor(NodeColor::Black);
        Trait::GetTreeNode(aNode).SetColor(NodeColor::Red);
        rbp_mrl_t = RotateLeft(aNode);
        Trait::GetTreeNode(node).SetLeft(rbp_mrl_t);
      } else {
        Trait::GetTreeNode(aNode).SetColor(NodeColor::Black);
      }
    } else {
      Trait::GetTreeNode(aNode).SetColor(NodeColor::Red);
      node = RotateLeft(aNode);
    }
    return node;
  }

  T* MoveRedRight(T* aNode)
  {
    T* node;
    T* rbp_mrr_t;
    rbp_mrr_t = Trait::GetTreeNode(aNode).Left();
    if (Trait::GetTreeNode(rbp_mrr_t).IsRed()) {
      T *rbp_mrr_u, *rbp_mrr_v;
      rbp_mrr_u = Trait::GetTreeNode(rbp_mrr_t).Right();
      rbp_mrr_v = Trait::GetTreeNode(rbp_mrr_u).Left();
      if (Trait::GetTreeNode(rbp_mrr_v).IsRed()) {
        Trait::GetTreeNode(rbp_mrr_u).SetColor(
          Trait::GetTreeNode(aNode).Color());
        Trait::GetTreeNode(rbp_mrr_v).SetColor(NodeColor::Black);
        rbp_mrr_u = RotateLeft(rbp_mrr_t);
        Trait::GetTreeNode(aNode).SetLeft(rbp_mrr_u);
        node = RotateRight(aNode);
        rbp_mrr_t = RotateLeft(aNode);
        Trait::GetTreeNode(node).SetRight(rbp_mrr_t);
      } else {
        Trait::GetTreeNode(rbp_mrr_t).SetColor(
          Trait::GetTreeNode(aNode).Color());
        Trait::GetTreeNode(rbp_mrr_u).SetColor(NodeColor::Red);
        node = RotateRight(aNode);
        rbp_mrr_t = RotateLeft(aNode);
        Trait::GetTreeNode(node).SetRight(rbp_mrr_t);
      }
      Trait::GetTreeNode(aNode).SetColor(NodeColor::Red);
    } else {
      Trait::GetTreeNode(rbp_mrr_t).SetColor(NodeColor::Red);
      rbp_mrr_t = Trait::GetTreeNode(rbp_mrr_t).Left();
      if (Trait::GetTreeNode(rbp_mrr_t).IsRed()) {
        Trait::GetTreeNode(rbp_mrr_t).SetColor(NodeColor::Black);
        node = RotateRight(aNode);
        rbp_mrr_t = RotateLeft(aNode);
        Trait::GetTreeNode(node).SetRight(rbp_mrr_t);
      } else {
        node = RotateLeft(aNode);
      }
    }
    return node;
  }
};

/*
 * The iterators simulate recursion via an array of pointers that store the
 * current path.  This is critical to performance, since a series of calls to
 * rb_{next,prev}() would require time proportional to (n lg n), whereas this
 * implementation only requires time proportional to (n).
 *
 * Since the iterators cache a path down the tree, any tree modification may
 * cause the cached path to become invalid.  In order to continue iteration,
 * use something like the following sequence:
 *
 *   {
 *       a_type *node, *tnode;
 *
 *       rb_foreach_begin(a_type, a_field, a_tree, node) {
 *           ...
 *           rb_next(a_type, a_field, a_cmp, a_tree, node, tnode);
 *           rb_remove(a_type, a_field, a_cmp, a_tree, node);
 *           ...
 *       } rb_foreach_end(a_type, a_field, a_tree, node)
 *   }
 *
 * Note that this idiom is not advised if every iteration modifies the tree,
 * since in that case there is no algorithmic complexity improvement over a
 * series of rb_{next,prev}() calls, thus making the setup overhead wasted
 * effort.
 */

/*
 * Avoid using variable-length arrays, at the cost of using more stack space.
 * Size the path arrays such that they are always large enough, even if a
 * tree consumes all of memory.  Since each node must contain a minimum of
 * two pointers, there can never be more nodes than:
 *
 *   1 << ((SIZEOF_PTR<<3) - (SIZEOF_PTR_2POW+1))
 *
 * Since the depth of a tree is limited to 3*lg(#nodes), the maximum depth
 * is:
 *
 *   (3 * ((SIZEOF_PTR<<3) - (SIZEOF_PTR_2POW+1)))
 *
 * This works out to a maximum depth of 87 and 180 for 32- and 64-bit
 * systems, respectively (approximatly 348 and 1440 bytes, respectively).
 */
#define rbp_f_height (3 * ((SIZEOF_PTR << 3) - (SIZEOF_PTR_2POW + 1)))

#define rb_foreach_begin(a_type, a_field, a_tree, a_var)                       \
  {                                                                            \
    {                                                                          \
      /* Initialize the path to contain the left spine.             */         \
      a_type* rbp_f_path[rbp_f_height];                                        \
      a_type* rbp_f_node;                                                      \
      unsigned rbp_f_depth = 0;                                                \
      if ((a_tree)->rbt_root != &(a_tree)->rbt_nil) {                          \
        rbp_f_path[rbp_f_depth] = (a_tree)->rbt_root;                          \
        rbp_f_depth++;                                                         \
        while ((rbp_f_node = a_field(rbp_f_path[rbp_f_depth - 1]).Left()) !=   \
               &(a_tree)->rbt_nil) {                                           \
          rbp_f_path[rbp_f_depth] = rbp_f_node;                                \
          rbp_f_depth++;                                                       \
        }                                                                      \
      }                                                                        \
      /* While the path is non-empty, iterate.                      */         \
      while (rbp_f_depth > 0) {                                                \
        (a_var) = rbp_f_path[rbp_f_depth - 1];

#define rb_foreach_end(a_type, a_field, a_tree, a_var)                         \
  /* Find the successor.                                    */                 \
  if ((rbp_f_node = a_field(rbp_f_path[rbp_f_depth - 1]).Right()) !=           \
      &(a_tree)->rbt_nil) {                                                    \
    /* The successor is the left-most node in the right   */                   \
    /* subtree.                                           */                   \
    rbp_f_path[rbp_f_depth] = rbp_f_node;                                      \
    rbp_f_depth++;                                                             \
    while ((rbp_f_node = a_field(rbp_f_path[rbp_f_depth - 1]).Left()) !=       \
           &(a_tree)->rbt_nil) {                                               \
      rbp_f_path[rbp_f_depth] = rbp_f_node;                                    \
      rbp_f_depth++;                                                           \
    }                                                                          \
  } else {                                                                     \
    /* The successor is above the current node.  Unwind   */                   \
    /* until a left-leaning edge is removed from the      */                   \
    /* path, or the path is empty.                        */                   \
    for (rbp_f_depth--; rbp_f_depth > 0; rbp_f_depth--) {                      \
      if (a_field(rbp_f_path[rbp_f_depth - 1]).Left() ==                       \
          rbp_f_path[rbp_f_depth]) {                                           \
        break;                                                                 \
      }                                                                        \
    }                                                                          \
  }                                                                            \
  }                                                                            \
  }                                                                            \
  }

#endif /* RB_H_ */