/**
   * Removes given value from the set and returns the instance stored in the set or {@code null} if
   * value was not found.
   *
   * @param val Value to remove.
   * @return The instance that was stored in the set or {@code null}.
   */
  @Nullable
  public V removex(V val) {
    A.notNull(val, "val");

    if (comp == null || !strict) {
      for (Iterator<V> it = vals.iterator(); it.hasNext(); ) {
        V v = it.next();

        if (v.equals(val)) {
          it.remove();

          return v;
        }
      }

      return null;
    }

    assert comp != null && strict;

    for (Iterator<V> it = vals.iterator(); it.hasNext(); ) {
      V v = it.next();

      // Prefer equals to comparator.
      if (v.equals(val)) {
        it.remove();

        return v;
      }

      if (comp.compare(v, val) > 0) break;
    }

    return null;
  }
  /** {@inheritDoc} */
  @SuppressWarnings({"unchecked"})
  @Override
  public boolean remove(Object val) {
    A.notNull(val, "val");

    return removex((V) val) != null;
  }
  /**
   * Either adds a value to set or does nothing if value is already present.
   *
   * @param val Value to add.
   * @return The instance of value from this set or {@code null} if value was added.
   */
  @Nullable
  public V addx(V val) {
    A.notNull(val, "val");

    if (comp == null) {
      for (V v : vals) if (v.equals(val)) return v;

      vals.add(val);

      return null;
    }

    if (strict) {
      for (ListIterator<V> it = vals.listIterator(); it.hasNext(); ) {
        V v = it.next();

        // Prefer equals to comparator.
        if (v.equals(val)) return v;

        int c = comp.compare(v, val);

        if (c == 0) throw new IllegalStateException("Inconsistent equals and compare methods.");

        if (c > 0) {
          // Back up.
          it.previous();

          it.add(val);

          return null;
        }
      }

      vals.add(val);

      return null;
    }

    // Full scan first.
    for (V v : vals) if (v.equals(val)) return v;

    for (ListIterator<V> it = vals.listIterator(); it.hasNext(); ) {
      V v = it.next();

      if (comp.compare(v, val) > 0) {
        do {
          // Back up.
          v = it.previous();
        } while (comp.compare(v, val) == 0);

        it.add(val);

        return null;
      }
    }

    vals.add(val);

    return null;
  }
  /** {@inheritDoc} */
  @Override
  public void setAttributes(Map<?, ?> attrs) {
    A.notNull(attrs, "attrs");

    synchronized (this.attrs) {
      this.attrs.putAll(attrs);
    }
  }
  /** {@inheritDoc} */
  @Override
  public void setAttribute(Object key, @Nullable Object val) {
    A.notNull(key, "key");

    synchronized (attrs) {
      attrs.put(key, val);
    }
  }
  /** {@inheritDoc} */
  @SuppressWarnings("unchecked")
  @Override
  public <K, V> V getAttribute(K key) {
    A.notNull(key, "key");

    synchronized (attrs) {
      return (V) attrs.get(key);
    }
  }
  /** {@inheritDoc} */
  @Override
  public R get(long timeout, TimeUnit unit) throws GridException {
    A.ensure(timeout >= 0, "timeout cannot be negative: " + timeout);
    A.notNull(unit, "unit");

    checkValid();

    try {
      long now = System.currentTimeMillis();

      long end = timeout == 0 ? Long.MAX_VALUE : now + MILLISECONDS.convert(timeout, unit);

      // Account for overflow.
      if (end < 0) end = Long.MAX_VALUE;

      synchronized (mux) {
        while (!done && !cancelled && now < end) {
          mux.wait(end - now);

          if (!done) now = System.currentTimeMillis();
        }

        if (done) {
          if (err != null) throw U.cast(err);

          return res;
        }

        if (cancelled) throw new GridFutureCancelledException("Future was cancelled: " + this);

        throw new GridFutureTimeoutException(
            "Timeout was reached before computation completed [duration="
                + duration()
                + "ms, timeout="
                + unit.toMillis(timeout)
                + "ms]");
      }
    } catch (InterruptedException e) {
      throw new GridInterruptedException(
          "Got interrupted while waiting for future to complete [duration="
              + duration()
              + "ms, timeout="
              + unit.toMillis(timeout)
              + "ms]",
          e);
    }
  }
  /** {@inheritDoc} */
  @SuppressWarnings({"unchecked"})
  @Override
  public boolean contains(Object val) {
    A.notNull(val, "val");

    if (comp != null && strict) {
      for (V v : vals) {
        // Prefer equals to comparator.
        if (v.equals(val)) return true;

        if (comp.compare(v, (V) val) > 0) break;
      }

      return false;
    }

    return vals.contains(val);
  }
  /**
   * Gets instance {@code e} stored in this set for which {@code e.equals(val)} returns {@code
   * true}.
   *
   * @param val Value to check for equality.
   * @return Instance stored in this set for which {@code e.equals(val)} returns {@code true}.
   */
  @Nullable
  public V get(V val) {
    A.notNull(val, "val");

    if (comp == null || !strict) {
      for (V v : vals) if (v.equals(val)) return v;

      return null;
    }

    assert comp != null && strict;

    for (V v : vals) {
      // Prefer equals to comparator.
      if (v.equals(val)) return v;

      if (comp.compare(v, val) > 0) break;
    }

    return null;
  }
  /** {@inheritDoc} */
  @Override
  public GridFuture<?> addData(K key, V val) throws GridException, IllegalStateException {
    A.notNull(key, "key");

    return addData(new Entry0<>(key, val));
  }
  /** {@inheritDoc} */
  @Override
  public GridFuture<?> addData(Map.Entry<K, V> entry) throws GridException, IllegalStateException {
    A.notNull(entry, "entry");

    return addData(F.asList(entry));
  }
  /** {@inheritDoc} */
  @Override
  public GridFuture<?> addData(Map<K, V> entries) throws IllegalStateException {
    A.notNull(entries, "entries");

    return addData(entries.entrySet());
  }
  /** {@inheritDoc} */
  @Override
  public void updater(GridDataLoadCacheUpdater<K, V> updater) {
    A.notNull(updater, "updater");

    this.updater = updater;
  }