static Node safeNext(Node b) {
   while (true) {
     Node n = b.next;
     if (n == null) return null;
     n.incRefCnt();
     if (n == b.next) return n;
     else release(n);
   }
 }
 public void found(Node n) {
   n.incRefCnt();
 }
    // only used by putAtomic and PutAtomicIfAbsent. Inside synchronized(b) and synchronized(this).
    private void putAtomicReally(
        Node b, int pos, double key, Object value, ConcurrentDoubleOrderedListMap orderedMap) {
      int len = len();
      if (len + 1 <= keys.length) {
        if (pos == len) { // in-place append in the current node
          keys[pos] = key;
          vals[pos] = value;
          length = len + 1;
          if (pos == 0) {
            orderedMap.skipListMap.put(keys[0], this);
          }
        } else { // copied to a new node, replacing the current node
          mark();
          Node n = Node.alloc();
          n.next = this.next;
          if (next != null) next.incRefCnt();
          double[] nkeys = n.keys;
          Object[] nvals = n.vals;
          n.length = len + 1;
          nodeCopy(keys, vals, 0, nkeys, nvals, 0, pos);
          nkeys[pos] = key;
          nvals[pos] = value;
          nodeCopy(keys, vals, pos, nkeys, nvals, pos + 1, len - pos);

          orderedMap.skipListMap.put(nkeys[0], n);
          b.casNext(this, n); // should always succeed.
          if (pos == 0) {
            orderedMap.skipListMap.remove(keys[0], this);
          }
          release(this);
          free(this);
        }
      } else { // requires 2 new nodes, to replace the current node
        mark();
        Node n1 = Node.alloc();
        double[] n1keys = n1.keys;
        Object[] n1vals = n1.vals;
        Node n2 = Node.alloc();
        double[] n2keys = n2.keys;
        Object[] n2vals = n2.vals;
        int l1 = len / 2, l2 = len - l1;
        if (pos < l1) { // key, value stored in n1
          n1.length = l1 + 1;
          n2.length = l2;

          nodeCopy(keys, vals, 0, n1keys, n1vals, 0, pos);
          n1keys[pos] = key;
          n1vals[pos] = value;
          nodeCopy(keys, vals, pos, n1keys, n1vals, pos + 1, l1 - pos);
          nodeCopy(keys, vals, l1, n2keys, n2vals, 0, l2);

          n1.next = n2;
          n2.next = this.next;
          if (next != null) next.incRefCnt();

          orderedMap.skipListMap.put(n1keys[0], n1);
          orderedMap.skipListMap.put(n2keys[0], n2);
          b.casNext(this, n1); // should always succeed.
          if (pos == 0) {
            orderedMap.skipListMap.remove(keys[0], this);
          }
          release(this);
          free(this);
        } else { // key,value is stored in n2
          n1.length = l1;
          n2.length = l2 + 1;
          int newpos = pos - l1;

          nodeCopy(keys, vals, 0, n1keys, n1vals, 0, l1);

          nodeCopy(keys, vals, l1, n2keys, n2vals, 0, newpos);
          n2keys[newpos] = key;
          n2vals[newpos] = value;
          nodeCopy(keys, vals, pos, n2keys, n2vals, newpos + 1, l2 - newpos);

          n1.next = n2;
          n2.next = this.next;
          if (next != null) next.incRefCnt();

          orderedMap.skipListMap.put(n1keys[0], n1);
          orderedMap.skipListMap.put(n2keys[0], n2);
          b.casNext(this, n1); // should always succeed.
          release(this);
          free(this);
        }
      }
    }