/** {@inheritDoc} */
  @Nullable
  @Override
  public V put(K k, V v) {
    A.notNull(k, "k", v, "v");

    V ret = super.put(k, v);

    onPut();

    return ret;
  }
  /** {@inheritDoc} */
  @Nullable
  @Override
  public V putIfAbsent(K k, V v) {
    A.notNull(k, "k", v, "v");

    V ret = super.putIfAbsent(k, v);

    // Handle size only if put succeeded.
    if (ret == null) onPut();

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

    try {
      return get0(unit.toNanos(timeout));
    } catch (InterruptedException e) {
      Thread.currentThread().interrupt();

      throw new IgniteInterruptedCheckedException(
          "Got interrupted while waiting for future to complete.", e);
    }
  }
  /** {@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} */
  @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;
  }