Java Code Examples for java.util.concurrent.atomic.AtomicReferenceFieldUpdater#compareAndSet()

The following examples show how to use java.util.concurrent.atomic.AtomicReferenceFieldUpdater#compareAndSet() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source Project: servicetalk   File: SubscriberUtils.java    License: Apache License 2.0 6 votes vote down vote up
/**
 * There are some scenarios where a completion {@link TerminalNotification} can be overridden with an error if
 * errors are produced asynchronously.
 * <p>
 * This method helps set {@link TerminalNotification} atomically providing such an override.
 *
 * @param toSet {@link TerminalNotification} to set.
 * @param overrideComplete Whether exisiting {@link TerminalNotification#complete()} should be overridden with the
 * {@code toSet}.
 * @param terminalNotificationUpdater {@link AtomicReferenceFieldUpdater} to access the current
 * {@link TerminalNotification}.
 * @param flagOwner instance of {@link R} that owns the current {@link TerminalNotification} field referenced by
 * {@code terminalNotificationUpdater}.
 * @param <R> Type of {@code flagOwner}.
 * @return {@code true} if {@code toSet} is updated as the current {@link TerminalNotification}.
 */
public static <R> boolean trySetTerminal(TerminalNotification toSet, boolean overrideComplete,
                 AtomicReferenceFieldUpdater<R, TerminalNotification> terminalNotificationUpdater, R flagOwner) {
    for (;;) {
        TerminalNotification curr = terminalNotificationUpdater.get(flagOwner);
        if (curr != null && !overrideComplete) {
            // Once terminated, terminalNotification will never be set back to null.
            return false;
        } else if (curr == null && terminalNotificationUpdater.compareAndSet(flagOwner, null, toSet)) {
            return true;
        } else if (curr != null && curr.cause() == null) {
            // Override complete
            if (terminalNotificationUpdater.compareAndSet(flagOwner, curr, toSet)) {
                return true;
            }
        } else {
            return false;
        }
    }
}
 
Example 2
Source Project: reactor-core   File: Operators.java    License: Apache License 2.0 6 votes vote down vote up
/**
 * A generic utility to atomically replace a subscription or cancel the replacement
 * if current subscription is marked as cancelled (as in {@link #cancelledSubscription()})
 * or was concurrently updated before.
 * <p>
 * The replaced subscription is itself cancelled.
 *
 * @param field The Atomic container
 * @param instance the instance reference
 * @param s the subscription
 * @param <F> the instance type
 *
 * @return true if replaced
 */
public static <F> boolean set(AtomicReferenceFieldUpdater<F, Subscription> field,
		F instance,
		Subscription s) {
	for (; ; ) {
		Subscription a = field.get(instance);
		if (a == CancelledSubscription.INSTANCE) {
			s.cancel();
			return false;
		}
		if (field.compareAndSet(instance, a, s)) {
			if (a != null) {
				a.cancel();
			}
			return true;
		}
	}
}
 
Example 3
/**
 * compareAndSet in one thread enables another waiting for value
 * to succeed
 */
public void testCompareAndSetInMultipleThreads() throws Exception {
    x = one;
    final AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer> a;
    a = updaterFor("x");

    Thread t = new Thread(new CheckedRunnable() {
        public void realRun() {
            while (!a.compareAndSet(AtomicReferenceFieldUpdaterTest.this, two, three))
                Thread.yield();
        }});

    t.start();
    assertTrue(a.compareAndSet(this, one, two));
    t.join(LONG_DELAY_MS);
    assertFalse(t.isAlive());
    assertSame(three, a.get(this));
}
 
Example 4
/**
 * Atomically set the field to a {@link Disposable} and dispose the old content.
 *
 * @param updater the target field updater
 * @param holder the target instance holding the field
 * @param newValue the new Disposable to set
 * @return true if successful, false if the field contains the {@link #DISPOSED} instance.
 */
public static <T> boolean set(AtomicReferenceFieldUpdater<T, Disposable> updater, T holder, @Nullable Disposable newValue) {
	for (;;) {
		Disposable current = updater.get(holder);
		if (current == DISPOSED) {
			if (newValue != null) {
				newValue.dispose();
			}
			return false;
		}
		if (updater.compareAndSet(holder, current, newValue)) {
			if (current != null) {
				current.dispose();
			}
			return true;
		}
	}
}
 
Example 5
/**
 * compareAndSet in one thread enables another waiting for value
 * to succeed
 */
public void testCompareAndSetInMultipleThreads() throws Exception {
    x = one;
    final AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer> a;
    a = updaterFor("x");

    Thread t = new Thread(new CheckedRunnable() {
        public void realRun() {
            while (!a.compareAndSet(AtomicReferenceFieldUpdaterTest.this, two, three))
                Thread.yield();
        }});

    t.start();
    assertTrue(a.compareAndSet(this, one, two));
    t.join(LONG_DELAY_MS);
    assertFalse(t.isAlive());
    assertSame(three, a.get(this));
}
 
Example 6
Source Project: java-katas   File: TestSolutionCompareAndSet.java    License: MIT License 5 votes vote down vote up
@Test
@Tag("PASSING")
@Order(2)
public void compareAndSetUsingAtomicReferenceFieldUpdater() {

    final AtomicReferenceFieldUpdater<TestSolutionCompareAndSet, Integer> valueUpdater =
            AtomicReferenceFieldUpdater.newUpdater(TestSolutionCompareAndSet.class,
                    Integer.class,
                    "privateVolatile");

    boolean exchanged = valueUpdater.compareAndSet(this, currentValue, newValue);

    assertTrue(exchanged,
            "The value should have been changed to 7, " +
                    "hence exchanged should be true"
            );

    assertEquals(newValue,
            valueUpdater.get(this),
            "The value of the privateVolatile should now be 7");

    exchanged = valueUpdater.compareAndSet(this, 2, 33);

    assertFalse(exchanged,
            "The value should not have changed since the expected value " +
                    "did not match, hence exchanged should be false"
            );

    assertEquals(newValue,
            valueUpdater.get(this),
            "The value of the privateVolatile should still be 7");
}
 
Example 7
Source Project: java-katas   File: TestKataCompareAndSet.java    License: MIT License 5 votes vote down vote up
@Test
@Tag("PASSING")
@Order(2)
public void compareAndSetUsingAtomicReferenceFieldUpdater() {

    final AtomicReferenceFieldUpdater<TestKataCompareAndSet, Integer> valueUpdater =
            AtomicReferenceFieldUpdater.newUpdater(TestKataCompareAndSet.class,
                    Integer.class,
                    "privateVolatile");

    boolean exchanged = valueUpdater.compareAndSet(this, currentValue, newValue);

    assertTrue(exchanged,
            "The value should have been changed to 7, " +
                    "hence exchanged should be true"
            );

    assertEquals(newValue,
            valueUpdater.get(this),
            "The value of the privateVolatile should now be 7");

    exchanged = valueUpdater.compareAndSet(this, 2, 33);

    assertFalse(exchanged,
            "The value should not have changed since the expected value " +
                    "did not match, hence exchanged should be false"
            );

    assertEquals(newValue,
            valueUpdater.get(this),
            "The value of the privateVolatile should still be 7");
}
 
Example 8
@Nullable
@Override
public <T> T put(final Key<T> key, final T value,
                 CopyOnWriteAsyncContextMap owner,
                 AtomicReferenceFieldUpdater<CopyOnWriteAsyncContextMap, CopyAsyncContextMap> mapUpdater) {
    return mapUpdater.compareAndSet(owner, this, new OneAsyncContextMap(key, value)) ? null :
            owner.put(key, value);
}
 
Example 9
Source Project: reactor-core   File: Exceptions.java    License: Apache License 2.0 5 votes vote down vote up
/**
 * Update an empty atomic reference with the given exception, or combine further added
 * exceptions together as suppressed exceptions under a root Throwable with
 * the {@code "Multiple exceptions"} message, if the atomic reference already holds
 * one. This is short-circuited if the reference contains {@link #TERMINATED}.
 * <p>
 * Since composite exceptions and traceback exceptions share the same underlying mechanism
 * of suppressed exceptions, a traceback could be made part of a composite exception.
 * Use {@link #unwrapMultipleExcludingTracebacks(Throwable)} to filter out such elements in
 * a composite if needed.
 *
 * @param <T> the parent instance type
 * @param field the target field updater
 * @param instance the parent instance for the field
 * @param exception the Throwable to add.
 *
 * @return true if added, false if the field contained the {@link #TERMINATED}
 * instance.
 * @see #unwrapMultiple(Throwable)
 */
public static <T> boolean addThrowable(AtomicReferenceFieldUpdater<T, Throwable> field,
		T instance,
		Throwable exception) {
	for (; ; ) {
		Throwable current = field.get(instance);

		if (current == TERMINATED) {
			return false;
		}

		if (current instanceof CompositeException) {
			//this is ok, composite exceptions are never singletons
			current.addSuppressed(exception);
			return true;
		}

		Throwable update;
		if (current == null) {
			update = exception;
		} else {
			update = multiple(current, exception);
		}

		if (field.compareAndSet(instance, current, update)) {
			return true;
		}
	}
}
 
Example 10
Source Project: sofa-tracer   File: SequenceGroups.java    License: Apache License 2.0 5 votes vote down vote up
static <T> boolean removeSequence(final T holder,
                                  final AtomicReferenceFieldUpdater<T, Sequence[]> sequenceUpdater,
                                  final Sequence sequence) {
    int numToRemove;
    Sequence[] oldSequences;
    Sequence[] newSequences;

    do {
        oldSequences = sequenceUpdater.get(holder);

        numToRemove = countMatching(oldSequences, sequence);

        if (0 == numToRemove) {
            break;
        }

        final int oldSize = oldSequences.length;
        newSequences = new Sequence[oldSize - numToRemove];

        for (int i = 0, pos = 0; i < oldSize; i++) {
            final Sequence testSequence = oldSequences[i];
            if (sequence != testSequence) {
                newSequences[pos++] = testSequence;
            }
        }
    } while (!sequenceUpdater.compareAndSet(holder, oldSequences, newSequences));

    return numToRemove != 0;
}
 
Example 11
/**
 * Object arguments for parameters of type T that are not
 * instances of the class passed to the newUpdater call will
 * result in a ClassCastException being thrown.
 */
public void testFieldUpdaters_ClassCastException() {
    // Use raw types to allow passing wrong object type, provoking CCE
    final AtomicLongFieldUpdater longUpdater = aLongFieldUpdater();
    final AtomicIntegerFieldUpdater intUpdater = anIntFieldUpdater();
    final AtomicReferenceFieldUpdater refUpdater = anIntegerFieldUpdater();
    final Object obj = new Object();
    for (Object x : new Object[]{ new Object(), null }) {
        Runnable[] throwingActions = {
            () -> longUpdater.get(x),
            () -> intUpdater.get(x),
            () -> refUpdater.get(x),

            () -> longUpdater.set(x, 17L),
            () -> intUpdater.set(x, 17),
            () -> refUpdater.set(x, (Integer) 17),

            () -> longUpdater.addAndGet(x, 17L),
            () -> intUpdater.addAndGet(x, 17),

            () -> longUpdater.getAndUpdate(x, y -> y),
            () -> intUpdater.getAndUpdate(x, y -> y),
            () -> refUpdater.getAndUpdate(x, y -> y),

            () -> longUpdater.compareAndSet(x, 17L, 42L),
            () -> intUpdater.compareAndSet(x, 17, 42),
            () -> refUpdater.compareAndSet(x, (Integer) 17, (Integer) 42),
        };
        assertThrows(ClassCastException.class, throwingActions);
    }
}
 
Example 12
private void mutateAdditionalResponseHeaders(
        AtomicReferenceFieldUpdater<DefaultServiceRequestContext, HttpHeaders> atomicUpdater,
        Consumer<HttpHeadersBuilder> mutator) {
    for (;;) {
        final HttpHeaders oldValue = atomicUpdater.get(this);
        final HttpHeadersBuilder builder = oldValue.toBuilder();
        mutator.accept(builder);
        final HttpHeaders newValue = builder.build();
        if (atomicUpdater.compareAndSet(this, oldValue, newValue)) {
            return;
        }
    }
}
 
Example 13
Source Project: jtransc   File: AtomicTest.java    License: Apache License 2.0 5 votes vote down vote up
static private void testAtomicReferenceFieldUpdater() {
	System.out.println("AtomicTest.testAtomicReferenceFieldUpdater:");
	AtomicTest obj = new AtomicTest();
	AtomicReferenceFieldUpdater<AtomicTest, Integer> updater = AtomicReferenceFieldUpdater.newUpdater(AtomicTest.class, Integer.class, "value");
	System.out.println(updater.get(obj));
	updater.set(obj, 5);
	System.out.println(updater.get(obj));
	updater.compareAndSet(obj, 4, -4);
	System.out.println(updater.get(obj));
	updater.compareAndSet(obj, 5, -5);
	System.out.println(updater.get(obj));
}
 
Example 14
Source Project: reactor-core   File: Operators.java    License: Apache License 2.0 5 votes vote down vote up
/**
 * Sets the given subscription once and returns true if successful, false
 * if the field has a subscription already or has been cancelled.
 * <p>
 * If the field already has a subscription, it is cancelled and the duplicate
 * subscription is reported (see {@link #reportSubscriptionSet()}).
 *
 * @param <F> the instance type containing the field
 * @param field the field accessor
 * @param instance the parent instance
 * @param s the subscription to set once
 * @return true if successful, false if the target was not empty or has been cancelled
 */
public static <F> boolean setOnce(AtomicReferenceFieldUpdater<F, Subscription> field, F instance, Subscription s) {
	Objects.requireNonNull(s, "subscription");
	Subscription a = field.get(instance);
	if (a == CancelledSubscription.INSTANCE) {
		s.cancel();
		return false;
	}
	if (a != null) {
		s.cancel();
		reportSubscriptionSet();
		return false;
	}

	if (field.compareAndSet(instance, null, s)) {
		return true;
	}

	a = field.get(instance);

	if (a == CancelledSubscription.INSTANCE) {
		s.cancel();
		return false;
	}

	s.cancel();
	reportSubscriptionSet();
	return false;
}
 
Example 15
Source Project: reactor-core   File: Disposables.java    License: Apache License 2.0 5 votes vote down vote up
/**
 * Atomically replace the {@link Disposable} in the field with the given new Disposable
 * but do not dispose the old one.
 *
 * @param updater the target field updater
 * @param holder the target instance holding the field
 * @param newValue the new Disposable to set, null allowed
 * @return true if the operation succeeded, false if the target field contained
 * the common {@link #DISPOSED} instance and the given disposable is not null but is disposed.
 */
static <T> boolean replace(AtomicReferenceFieldUpdater<T, Disposable> updater, T holder, @Nullable Disposable newValue) {
	for (;;) {
		Disposable current = updater.get(holder);
		if (current == DISPOSED) {
			if (newValue != null) {
				newValue.dispose();
			}
			return false;
		}
		if (updater.compareAndSet(holder, current, newValue)) {
			return true;
		}
	}
}
 
Example 16
/**
 * Atomically set the field to the given non-null {@link Disposable} and return true,
 * or return false if the field is non-null.
 * If the target field contains the common {@link #DISPOSED} instance, the supplied disposable
 * is disposed. If the field contains other non-null {@link Disposable}, an {@link IllegalStateException}
 * is signalled to the {@code errorCallback}.
 *
 * @param updater the target field updater
 * @param holder the target instance holding the field
 * @param newValue the new Disposable to set, not null
 * @return true if the operation succeeded, false
 */
public static <T> boolean setOnce(AtomicReferenceFieldUpdater<T, Disposable> updater, T holder, Disposable newValue,
		Consumer<RuntimeException> errorCallback) {
	Objects.requireNonNull(newValue, "newValue is null");
	if (!updater.compareAndSet(holder, null, newValue)) {
		newValue.dispose();
		if (updater.get(holder) != DISPOSED) {
			errorCallback.accept(new IllegalStateException("Disposable already pushed"));
		}
		return false;
	}
	return true;
}
 
Example 17
/**
 * Atomically try to set the given {@link Disposable} on the field if it is null or
 * disposes it if the field contains {@link #DISPOSED}.
 *
 * @param updater the target field updater
 * @param holder the target instance holding the field
 * @param newValue the disposable to set
 * @return true if successful, false otherwise
 */
public static <T> boolean trySet(AtomicReferenceFieldUpdater<T, Disposable> updater, T holder, Disposable newValue) {
	if (!updater.compareAndSet(holder, null, newValue)) {
		if (updater.get(holder) == DISPOSED) {
			newValue.dispose();
		}
		return false;
	}
	return true;
}
 
Example 18
Source Project: reactor-core   File: RingBuffer.java    License: Apache License 2.0 5 votes vote down vote up
static <T> void addSequence(final T holder,
		final AtomicReferenceFieldUpdater<T, Sequence[]> updater,
		final Sequence sequence) {

	Sequence[] updatedSequences;
	Sequence[] currentSequences;

	do {
		currentSequences = updater.get(holder);
		updatedSequences = copyOf(currentSequences, currentSequences.length + 1);

		updatedSequences[currentSequences.length] = sequence;
	}
	while (!updater.compareAndSet(holder, currentSequences, updatedSequences));
}
 
Example 19
Source Project: reactor-core   File: RingBuffer.java    License: Apache License 2.0 5 votes vote down vote up
static <T> boolean removeSequence(final T holder,
		final AtomicReferenceFieldUpdater<T, Sequence[]> sequenceUpdater,
		final Sequence sequence) {
	int numToRemove;
	Sequence[] oldSequences;
	Sequence[] newSequences;

	do {
		oldSequences = sequenceUpdater.get(holder);

		numToRemove = countMatching(oldSequences, sequence);

		if (0 == numToRemove) {
			break;
		}

		final int oldSize = oldSequences.length;
		newSequences = new Sequence[oldSize - numToRemove];

		for (int i = 0, pos = 0; i < oldSize; i++) {
			final Sequence testSequence = oldSequences[i];
			if (sequence != testSequence) {
				newSequences[pos++] = testSequence;
			}
		}
	}
	while (!sequenceUpdater.compareAndSet(holder, oldSequences, newSequences));

	return numToRemove != 0;
}
 
Example 20
Source Project: reactor-core   File: Operators.java    License: Apache License 2.0 5 votes vote down vote up
/**
 * A generic utility to atomically replace a subscription or cancel the replacement
 * if the current subscription is marked as already cancelled (as in
 * {@link #cancelledSubscription()}).
 *
 * @param field The Atomic container
 * @param instance the instance reference
 * @param s the subscription
 * @param <F> the instance type
 *
 * @return true if replaced
 */
public static <F> boolean replace(AtomicReferenceFieldUpdater<F, Subscription> field,
		F instance,
		Subscription s) {
	for (; ; ) {
		Subscription a = field.get(instance);
		if (a == CancelledSubscription.INSTANCE) {
			s.cancel();
			return false;
		}
		if (field.compareAndSet(instance, a, s)) {
			return true;
		}
	}
}