static <K> TreeNode<K> balanceInsertion(TreeNode<K> root, TreeNode<K> x) {
      x.red = true;
      for (TreeNode<K> xp, xpp, xppl, xppr;;) {
        if ((xp = x.parent) == null) {
          x.red = false;
          return x;
        } else if (!xp.red || (xpp = xp.parent) == null) {
          return root;
        }
        if (xp == (xppl = xpp.left)) {
          if ((xppr = xpp.right) != null && xppr.red) {
            xppr.red = false;
            xp.red = false;
            xpp.red = true;
            x = xpp;
          } else {
            if (x == xp.right) {
              root = rotateLeft(root, x = xp);
              xpp = (xp = x.parent) == null ? null : xp.parent;
            }
            if (xp != null) {
              xp.red = false;
              if (xpp != null) {
                xpp.red = true;
                root = rotateRight(root, xpp);
              }
            }
          }
        } else {
          if (xppl != null && xppl.red) {
            xppl.red = false;
            xp.red = false;
            xpp.red = true;
            x = xpp;
          } else {
            if (x == xp.left) {
              root = rotateRight(root, x = xp);
              xpp = (xp = x.parent) == null ? null : xp.parent;
            }
            if (xp != null) {
              xp.red = false;
              if (xpp != null) {
                xpp.red = true;
                root = rotateLeft(root, xpp);
              }
            }
          }
        }
      }
    }
Removes the given node, that must be present before this call. This is messier than typical
red-black deletion code because we cannot swap the contents of an interior node with a leaf
successor that is pinned by "next" pointers that are accessible independently of lock. So
instead we swap the tree linkages.

@return true if now too small, so should be untreeified
geode-core/src/main/java/org/apache/geode/internal/concurrent/CompactConcurrentHashSet2.java