class Item<V> {
        /** */
        private long idx;

        /** */
        @GridToStringInclude
        private V item;

        /**
         *
         */
        Item() {
            // No-op.
        }

        /**
         * @return Item.
         */
        synchronized V item() {
            return item;
        }

        /**
         * @param newIdx Index.
         * @param newItem Item.
         * @param maxIdxDiff Max difference in indexes.
         * @return Evicted value on success or {@code null} if update failed.
         * @throws InterruptedException If interrupted.
         */
        @Nullable synchronized V update(long newIdx, V newItem, long maxIdxDiff) throws InterruptedException {
            assert newIdx >= 0;

            // Thread should wait and allow previous update to finish.
            while (newIdx - idx > maxIdxDiff)
                wait();

            V old = item;

            idx = newIdx;
            item = newItem;

            notifyAll();

            return old;
        }

        /**
         * @param newIdx Index.
         * @param newItem Item.
         * @param maxIdxDiff Max difference in indexes.
         * @param c Closure applied on evicted object before eviction.
         * @return Evicted value on success or {@code null} if update failed.
         * @throws InterruptedException If interrupted.
         * @throws IgniteCheckedException If closure throws exception.
         */
        @Nullable synchronized V update(long newIdx, V newItem, long maxIdxDiff, @Nullable IgniteInClosureX<V> c)
            throws InterruptedException, IgniteCheckedException {<FILL_FUNCTION_BODY>}

        /**
         * @return Item data and index.
         */
        synchronized T2<V, Long> get() {
            return new T2<>(item, idx);
        }

        /** {@inheritDoc} */
        @Override public synchronized String toString() {
            return S.toString(Item.class, this, "hash=" + System.identityHashCode(this));
        }
    }

            assert newIdx >= 0;

            // Thread should wait and allow previous update to finish.
            while (newIdx - idx > maxIdxDiff)
                wait();

            idx = newIdx; // Index should be updated even if closure fails.

            if (c != null && item != null)
                c.applyx(item);

            V old = item;

            item = newItem;

            notifyAll();

            return old;
        
<no_super_class>