/** {@inheritDoc} */
  @Override
  public boolean compareAndSet(T expVal, T newVal, S expStamp, S newStamp) throws GridException {
    checkRemoved();

    return CU.outTx(
        internalCompareAndSet(
            F0.equalTo(expVal),
            wrapperClosure(newVal),
            F0.equalTo(expStamp),
            wrapperClosure(newStamp)),
        ctx);
  }
  /**
   * Synchronous sequence update operation. Will add given amount to the sequence value.
   *
   * @param l Increment amount.
   * @param updateCall Cache call that will update sequence reservation count in accordance with l.
   * @param updated If {@code true}, will return sequence value after update, otherwise will return
   *     sequence value prior to update.
   * @return Sequence value.
   * @throws GridException If update failed.
   */
  private long internalUpdate(long l, @Nullable Callable<Long> updateCall, boolean updated)
      throws GridException {
    checkRemoved();

    assert l > 0;

    lock.lock();

    try {
      // If reserved range isn't exhausted.
      if (locVal + l <= upBound) {
        long curVal = locVal;

        locVal += l;

        return updated ? locVal : curVal;
      }
    } finally {
      lock.unlock();
    }

    if (updateCall == null) updateCall = internalUpdate(l, updated);

    while (true) {
      if (updateGuard.compareAndSet(false, true)) {
        try {
          // This call must be outside lock.
          return CU.outTx(updateCall, ctx);
        } finally {
          lock.lock();

          try {
            updateGuard.set(false);

            cond.signalAll();
          } finally {
            lock.unlock();
          }
        }
      } else {
        lock.lock();

        try {
          while (locVal >= upBound && updateGuard.get()) {
            try {
              cond.await(500, MILLISECONDS);
            } catch (InterruptedException e) {
              throw new GridInterruptedException(e);
            }
          }

          checkRemoved();

          // If reserved range isn't exhausted.
          if (locVal + l <= upBound) {
            long curVal = locVal;

            locVal += l;

            return updated ? locVal : curVal;
          }
        } finally {
          lock.unlock();
        }
      }
    }
  }
  /** {@inheritDoc} */
  @Override
  public boolean compareAndSet(T expVal, T newVal) throws GridException {
    checkRemoved();

    return CU.outTx(internalCompareAndSet(wrapperPredicate(expVal), wrapperClosure(newVal)), ctx);
  }
  /** {@inheritDoc} */
  @Override
  public void set(T val) throws GridException {
    checkRemoved();

    CU.outTx(internalSet(val), ctx);
  }
  /** {@inheritDoc} */
  @Override
  public T get() throws GridException {
    checkRemoved();

    return CU.outTx(getCall, ctx);
  }
  /** {@inheritDoc} */
  @Override
  public T value() throws GridException {
    checkRemoved();

    return CU.outTx(valCall, ctx);
  }
  /** {@inheritDoc} */
  @Override
  public S stamp() throws GridException {
    checkRemoved();

    return CU.outTx(stampCall, ctx);
  }