boolean removeTreeNode(TreeNode<K> p) {
      TreeNode<K> next = (TreeNode<K>) p.next;
      TreeNode<K> pred = p.prev; // unlink traversal pointers
      TreeNode<K> r, rl;
      if (pred == null) {
        first = next;
      } else {
        pred.next = next;
      }
      if (next != null) {
        next.prev = pred;
      }
      if (first == null) {
        root = null;
        return true;
      }
      if ((r = root) == null || r.right == null || // too small
          (rl = r.left) == null || rl.left == null) {
        return true;
      }
      lockRoot();
      try {
        TreeNode<K> replacement;
        TreeNode<K> pl = p.left;
        TreeNode<K> pr = p.right;
        if (pl != null && pr != null) {
          TreeNode<K> s = pr, sl;
          while ((sl = s.left) != null) // find successor
          {
            s = sl;
          }
          boolean c = s.red;
          s.red = p.red;
          p.red = c; // swap colors
          TreeNode<K> sr = s.right;
          TreeNode<K> pp = p.parent;
          if (s == pr) { // p was s's direct parent
            p.parent = s;
            s.right = p;
          } else {
            TreeNode<K> sp = s.parent;
            if ((p.parent = sp) != null) {
              if (s == sp.left) {
                sp.left = p;
              } else {
                sp.right = p;
              }
            }
            s.right = pr;
            pr.parent = s;
          }
          p.left = null;
          if ((p.right = sr) != null) {
            sr.parent = p;
          }
          s.left = pl;
          pl.parent = s;
          if ((s.parent = pp) == null) {
            r = s;
          } else if (p == pp.left) {
            pp.left = s;
          } else {
            pp.right = s;
          }
          if (sr != null) {
            replacement = sr;
          } else {
            replacement = p;
          }
        } else if (pl != null) {
          replacement = pl;
        } else if (pr != null) {
          replacement = pr;
        } else {
          replacement = p;
        }
        if (replacement != p) {
          TreeNode<K> pp = replacement.parent = p.parent;
          if (pp == null) {
            r = replacement;
          } else if (p == pp.left) {
            pp.left = replacement;
          } else {
            pp.right = replacement;
          }
          p.left = p.right = p.parent = null;
        }

        root = (p.red) ? r : balanceDeletion(r, replacement);

        if (p == replacement) { // detach pointers
          TreeNode<K> pp;
          if ((pp = p.parent) != null) {
            if (p == pp.left) {
              pp.left = null;
            } else if (p == pp.right) {
              pp.right = null;
            }
            p.parent = null;
          }
        }
      } finally {
        unlockRoot();
      }
      assert checkInvariants(root);
      return false;
    }
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