下面列出了怎么用java.util.concurrent.atomic.AtomicReferenceFieldUpdater的API类实例代码及写法,或者点击链接到github查看源代码。
/**
* 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;
}
}
}
@SuppressWarnings("unchecked")
@Override
public <T> T put(final Key<T> key, final T value, CopyOnWriteAsyncContextMap owner,
AtomicReferenceFieldUpdater<CopyOnWriteAsyncContextMap, CopyAsyncContextMap> mapUpdater) {
assert keyOne != null && keyTwo != null;
if (keyOne.equals(key)) {
return mapUpdater.compareAndSet(owner, this, new TwoAsyncContextMap(keyOne, value, keyTwo, valueTwo)) ?
(T) valueOne : owner.put(key, value);
} else if (keyTwo.equals(key)) {
return mapUpdater.compareAndSet(owner, this, new TwoAsyncContextMap(keyOne, valueOne, keyTwo, value)) ?
(T) valueTwo : owner.put(key, value);
}
return mapUpdater.compareAndSet(owner, this,
new ThreeAsyncContextMap(keyOne, valueOne, keyTwo, valueTwo, key, value)) ?
null : owner.put(key, value);
}
/**
* 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;
}
}
}
@Override
public boolean removeAll(final Iterable<Key<?>> entries, CopyOnWriteAsyncContextMap owner,
AtomicReferenceFieldUpdater<CopyOnWriteAsyncContextMap, CopyAsyncContextMap> mapUpdater) {
assert keyOne != null && keyTwo != null;
MutableInt removeIndexMask = new MutableInt();
entries.forEach(k -> {
if (keyOne.equals(k)) {
removeIndexMask.value |= 0x1;
} else if (keyTwo.equals(k)) {
removeIndexMask.value |= 0x2;
}
});
if ((removeIndexMask.value & 0x3) == 0x3) {
return mapUpdater.compareAndSet(owner, this, EmptyAsyncContextMap.INSTANCE) || owner.removeAll(entries);
} else if ((removeIndexMask.value & 0x2) == 0x2) {
return mapUpdater.compareAndSet(owner, this, new OneAsyncContextMap(keyOne, valueOne)) ||
owner.removeAll(entries);
} else if ((removeIndexMask.value & 0x1) == 0x1) {
return mapUpdater.compareAndSet(owner, this, new OneAsyncContextMap(keyTwo, valueTwo)) ||
owner.removeAll(entries);
}
return false;
}
/**
* 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));
}
@Override
public boolean removeAll(final Iterable<Key<?>> entries, CopyOnWriteAsyncContextMap owner,
AtomicReferenceFieldUpdater<CopyOnWriteAsyncContextMap, CopyAsyncContextMap> mapUpdater) {
assert keyOne != null && keyTwo != null && keyThree != null && keyFour != null;
MutableInt removeIndexMask = new MutableInt();
entries.forEach(k -> {
if (keyOne.equals(k)) {
removeIndexMask.value |= 0x1;
} else if (keyTwo.equals(k)) {
removeIndexMask.value |= 0x2;
} else if (keyThree.equals(k)) {
removeIndexMask.value |= 0x4;
} else if (keyFour.equals(k)) {
removeIndexMask.value |= 0x8;
}
});
CopyAsyncContextMap newMap = removeAll(removeIndexMask);
if (newMap == null) {
return false;
}
return mapUpdater.compareAndSet(owner, this, newMap) || owner.removeAll(entries);
}
@SuppressWarnings("unchecked")
@Nullable
@Override
public <T> T put(Key<T> key, @Nullable T value, CopyOnWriteAsyncContextMap owner,
AtomicReferenceFieldUpdater<CopyOnWriteAsyncContextMap, CopyAsyncContextMap> mapUpdater) {
int i = findIndex(Objects.requireNonNull(key));
final Object[] context;
if (i < 0) {
context = new Object[this.context.length + 2];
arraycopy(this.context, 0, context, 0, this.context.length);
context[this.context.length] = key;
context[this.context.length + 1] = value;
} else {
context = new Object[this.context.length];
arraycopy(this.context, 0, context, 0, i + 1);
context[i + 1] = value;
if (i + 2 < context.length) {
arraycopy(this.context, i + 2, context, i + 2, context.length - i - 2);
}
}
return mapUpdater.compareAndSet(owner, this, new SevenOrMoreAsyncContextMap(context)) ?
(T) this.context[i + 1] : null;
}
@Override
public boolean removeAll(Iterable<Key<?>> entries, CopyOnWriteAsyncContextMap owner,
AtomicReferenceFieldUpdater<CopyOnWriteAsyncContextMap, CopyAsyncContextMap> mapUpdater) {
GrowableIntArray indexesToRemove = new GrowableIntArray(3);
entries.forEach(key -> {
int keyIndex = findIndex(key);
if (keyIndex >= 0) {
indexesToRemove.add(keyIndex);
}
});
CopyAsyncContextMap newMap = removeAll(indexesToRemove);
if (newMap == null) {
return false;
}
return mapUpdater.compareAndSet(owner, this, newMap) || owner.removeAll(entries);
}
/**
* 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));
}
/**
* 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.
*/
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;
}
}
}
/**
* 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;
}
}
}
SafeAtomicHelper(
AtomicReferenceFieldUpdater<Waiter, Thread> waiterThreadUpdater,
AtomicReferenceFieldUpdater<Waiter, Waiter> waiterNextUpdater,
AtomicReferenceFieldUpdater<AbstractFuture, Waiter> waitersUpdater,
AtomicReferenceFieldUpdater<AbstractFuture, Listener> listenersUpdater,
AtomicReferenceFieldUpdater<AbstractFuture, Object> valueUpdater) {
this.waiterThreadUpdater = waiterThreadUpdater;
this.waiterNextUpdater = waiterNextUpdater;
this.waitersUpdater = waitersUpdater;
this.listenersUpdater = listenersUpdater;
this.valueUpdater = valueUpdater;
}
/**
* 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;
}
}
}
/**
* get returns the last value lazySet by same thread
*/
public void testGetLazySet() {
AtomicReferenceFieldUpdater<AtomicReferenceFieldUpdaterTest, Integer> a;
a = updaterFor("x");
x = one;
assertSame(one, a.get(this));
a.lazySet(this, two);
assertSame(two, a.get(this));
a.lazySet(this, m3);
assertSame(m3, a.get(this));
}
@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");
}
/**
* 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;
}
@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);
}
@Nullable
@Override
public <T> T remove(final Key<T> key,
CopyOnWriteAsyncContextMap owner,
AtomicReferenceFieldUpdater<CopyOnWriteAsyncContextMap, CopyAsyncContextMap> mapUpdater) {
return null;
}
@SuppressWarnings("unchecked")
@Override
public <T> T put(final Key<T> key, final T value, CopyOnWriteAsyncContextMap owner,
AtomicReferenceFieldUpdater<CopyOnWriteAsyncContextMap, CopyAsyncContextMap> mapUpdater) {
assert this.key != null;
if (this.key.equals(key)) {
return mapUpdater.compareAndSet(owner, this, new OneAsyncContextMap(this.key, value)) ? (T) this.value :
owner.put(key, value);
}
return mapUpdater.compareAndSet(owner, this, new TwoAsyncContextMap(this.key, this.value, key, value)) ?
null : owner.put(key, value);
}
@SuppressWarnings("unchecked")
@Nullable
@Override
public <T> T remove(final Key<T> key, CopyOnWriteAsyncContextMap owner,
AtomicReferenceFieldUpdater<CopyOnWriteAsyncContextMap, CopyAsyncContextMap> mapUpdater) {
assert this.key != null;
if (this.key.equals(key)) {
return mapUpdater.compareAndSet(owner, this, EmptyAsyncContextMap.INSTANCE) ?
(T) value : owner.remove(key);
}
return null;
}
@Override
public boolean removeAll(final Iterable<Key<?>> entries, CopyOnWriteAsyncContextMap owner,
AtomicReferenceFieldUpdater<CopyOnWriteAsyncContextMap, CopyAsyncContextMap> mapUpdater) {
assert this.key != null;
MutableInt index = new MutableInt();
entries.forEach(key -> {
if (this.key.equals(key)) {
index.value = 1;
}
});
if (index.value != 0) {
return mapUpdater.compareAndSet(owner, this, EmptyAsyncContextMap.INSTANCE) || owner.removeAll(entries);
}
return false;
}
static <T, V> AtomicReferenceFieldUpdater<T, V> newRefUpdater(Class<T> tclass, Class<V> vclass, String fieldName) {
if (AVAILABLE) {
return AtomicReferenceFieldUpdater.newUpdater(tclass, vclass, fieldName);
} else {
return null;
}
}
/**
* 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;
}
@SuppressWarnings("unchecked")
@Nullable
@Override
public <T> T remove(final Key<T> key, CopyOnWriteAsyncContextMap owner,
AtomicReferenceFieldUpdater<CopyOnWriteAsyncContextMap, CopyAsyncContextMap> mapUpdater) {
assert keyOne != null && keyTwo != null && keyThree != null && keyFour != null;
if (keyOne.equals(key)) {
return mapUpdater.compareAndSet(owner, this,
new ThreeAsyncContextMap(keyTwo, valueTwo, keyThree, valueThree, keyFour, valueFour)) ?
(T) valueOne : owner.remove(key);
}
if (keyTwo.equals(key)) {
return mapUpdater.compareAndSet(owner, this,
new ThreeAsyncContextMap(keyOne, valueOne, keyThree, valueThree, keyFour, valueFour)) ?
(T) valueTwo : owner.remove(key);
}
if (keyThree.equals(key)) {
return mapUpdater.compareAndSet(owner, this,
new ThreeAsyncContextMap(keyOne, valueOne, keyTwo, valueTwo, keyFour, valueFour)) ?
(T) valueThree : owner.remove(key);
}
if (keyFour.equals(key)) {
return mapUpdater.compareAndSet(owner, this,
new ThreeAsyncContextMap(keyOne, valueOne, keyTwo, valueTwo, keyThree, valueThree)) ?
(T) valueFour : owner.remove(key);
}
return null;
}
@SuppressWarnings("unchecked")
@Nullable
@Override
public <T> T put(final Key<T> key, final T value, CopyOnWriteAsyncContextMap owner,
AtomicReferenceFieldUpdater<CopyOnWriteAsyncContextMap, CopyAsyncContextMap> mapUpdater) {
assert keyOne != null && keyTwo != null && keyThree != null && keyFour != null && keyFive != null;
if (keyOne.equals(key)) {
return mapUpdater.compareAndSet(owner, this,
new FiveAsyncContextMap(keyOne, value, keyTwo, valueTwo, keyThree, valueThree,
keyFour, valueFour, keyFive, valueFive)) ? (T) valueOne : owner.put(key, value);
} else if (keyTwo.equals(key)) {
return mapUpdater.compareAndSet(owner, this,
new FiveAsyncContextMap(keyOne, valueOne, keyTwo, value, keyThree, valueThree,
keyFour, valueFour, keyFive, valueFive)) ? (T) valueTwo : owner.put(key, value);
} else if (keyThree.equals(key)) {
return mapUpdater.compareAndSet(owner, this,
new FiveAsyncContextMap(keyOne, valueOne, keyTwo, valueTwo, keyThree, value, keyFour, valueFour,
keyFive, valueFive)) ? (T) valueThree : owner.put(key, value);
} else if (keyFour.equals(key)) {
return mapUpdater.compareAndSet(owner, this, new FiveAsyncContextMap(keyOne, valueOne, keyTwo, valueTwo,
keyThree, valueThree, keyFour, value, keyFive, valueFive)) ?
(T) valueFour : owner.put(key, value);
} else if (keyFive.equals(key)) {
return mapUpdater.compareAndSet(owner, this,
new FiveAsyncContextMap(keyOne, valueOne, keyTwo, valueTwo, keyThree, valueThree,
keyFour, valueFour, keyFive, value)) ? (T) valueFive : owner.put(key, value);
}
return mapUpdater.compareAndSet(owner, this,
new SixAsyncContextMap(keyOne, valueOne, keyTwo, valueTwo, keyThree, valueThree, keyFour, valueFour,
keyFive, valueFive, key, value)) ? null : owner.put(key, value);
}
@SuppressWarnings("unchecked")
@Nullable
@Override
public <T> T remove(final Key<T> key, CopyOnWriteAsyncContextMap owner,
AtomicReferenceFieldUpdater<CopyOnWriteAsyncContextMap, CopyAsyncContextMap> mapUpdater) {
assert keyOne != null && keyTwo != null && keyThree != null && keyFour != null && keyFive != null;
if (keyOne.equals(key)) {
return mapUpdater.compareAndSet(owner, this, new FourAsyncContextMap(keyTwo, valueTwo, keyThree,
valueThree, keyFour, valueFour, keyFive, valueFive)) ? (T) valueOne : owner.remove(key);
}
if (keyTwo.equals(key)) {
return mapUpdater.compareAndSet(owner, this, new FourAsyncContextMap(keyOne, valueOne, keyThree,
valueThree, keyFour, valueFour, keyFive, valueFive)) ? (T) valueTwo : owner.remove(key);
}
if (keyThree.equals(key)) {
return mapUpdater.compareAndSet(owner, this, new FourAsyncContextMap(keyOne, valueOne, keyTwo, valueTwo,
keyFour, valueFour, keyFive, valueFive)) ? (T) valueThree : owner.remove(key);
}
if (keyFour.equals(key)) {
return mapUpdater.compareAndSet(owner, this, new FourAsyncContextMap(keyOne, valueOne, keyTwo, valueTwo,
keyThree, valueThree, keyFive, valueFive)) ? (T) valueFour : owner.remove(key);
}
if (keyFive.equals(key)) {
return mapUpdater.compareAndSet(owner, this, new FourAsyncContextMap(keyOne, valueOne, keyTwo, valueTwo,
keyThree, valueThree, keyFour, valueFour)) ? (T) valueFive : owner.remove(key);
}
return null;
}
@SuppressWarnings("unchecked")
@Nullable
@Override
public <T> T put(final Key<T> key, final T value, CopyOnWriteAsyncContextMap owner,
AtomicReferenceFieldUpdater<CopyOnWriteAsyncContextMap, CopyAsyncContextMap> mapUpdater) {
assert keyOne != null && keyTwo != null && keyThree != null && keyFour != null && keyFive != null &&
keySix != null;
if (keyOne.equals(key)) {
return mapUpdater.compareAndSet(owner, this, new SixAsyncContextMap(keyOne, value, keyTwo, valueTwo,
keyThree, valueThree, keyFour, valueFour, keyFive, valueFive, keySix, valueSix)) ?
(T) valueOne : owner.put(key, value);
} else if (keyTwo.equals(key)) {
return mapUpdater.compareAndSet(owner, this, new SixAsyncContextMap(keyOne, valueOne, keyTwo, value,
keyThree, valueThree, keyFour, valueFour, keyFive, valueFive, keySix, valueSix)) ?
(T) valueTwo : owner.put(key, value);
} else if (keyThree.equals(key)) {
return mapUpdater.compareAndSet(owner, this, new SixAsyncContextMap(keyOne, valueOne, keyTwo, valueTwo,
keyThree, value, keyFour, valueFour, keyFive, valueFive, keySix, valueSix)) ?
(T) valueThree : owner.put(key, value);
} else if (keyFour.equals(key)) {
return mapUpdater.compareAndSet(owner, this, new SixAsyncContextMap(keyOne, valueOne, keyTwo, valueTwo,
keyThree, valueThree, keyFour, value, keyFive, valueFive, keySix, valueSix)) ?
(T) valueFour : owner.put(key, value);
} else if (keyFive.equals(key)) {
return mapUpdater.compareAndSet(owner, this, new SixAsyncContextMap(keyOne, valueOne, keyTwo, valueTwo,
keyThree, valueThree, keyFour, valueFour, keyFive, value, keySix, valueSix)) ?
(T) valueFive : owner.put(key, value);
} else if (keySix.equals(key)) {
return mapUpdater.compareAndSet(owner, this, new SixAsyncContextMap(keyOne, valueOne, keyTwo, valueTwo,
keyThree, valueThree, keyFour, valueFour, keyFive, valueFive, keySix, value)) ?
(T) valueSix : owner.put(key, value);
}
return mapUpdater.compareAndSet(owner, this, new SevenOrMoreAsyncContextMap(keyOne, valueOne, keyTwo,
valueTwo, keyThree, valueThree, keyFour, valueFour, keyFive, valueFive, keySix, valueSix,
key, value)) ? null : owner.put(key, value);
}
@SuppressWarnings("unchecked")
@Nullable
@Override
public <T> T remove(final Key<T> key, CopyOnWriteAsyncContextMap owner,
AtomicReferenceFieldUpdater<CopyOnWriteAsyncContextMap, CopyAsyncContextMap> mapUpdater) {
assert keyOne != null && keyTwo != null && keyThree != null && keyFour != null && keyFive != null &&
keySix != null;
if (keyOne.equals(key)) {
return mapUpdater.compareAndSet(owner, this, new FiveAsyncContextMap(keyTwo, valueTwo, keyThree,
valueThree, keyFour, valueFour, keyFive, valueFive, keySix, valueSix)) ?
(T) valueOne : owner.remove(key);
}
if (keyTwo.equals(key)) {
return mapUpdater.compareAndSet(owner, this, new FiveAsyncContextMap(keyOne, valueOne, keyThree,
valueThree, keyFour, valueFour, keyFive, valueFive, keySix, valueSix)) ?
(T) valueTwo : owner.remove(key);
}
if (keyThree.equals(key)) {
return mapUpdater.compareAndSet(owner, this, new FiveAsyncContextMap(keyOne, valueOne, keyTwo, valueTwo,
keyFour, valueFour, keyFive, valueFive, keySix, valueSix)) ? (T) valueThree : owner.remove(key);
}
if (keyFour.equals(key)) {
return mapUpdater.compareAndSet(owner, this, new FiveAsyncContextMap(keyOne, valueOne, keyTwo, valueTwo,
keyThree, valueThree, keyFive, valueFive, keySix, valueSix)) ? (T) valueFour : owner.remove(key);
}
if (keyFive.equals(key)) {
return mapUpdater.compareAndSet(owner, this, new FiveAsyncContextMap(keyOne, valueOne, keyTwo, valueTwo,
keyThree, valueThree, keyFour, valueFour, keySix, valueSix)) ? (T) valueFive : owner.remove(key);
}
if (keySix.equals(key)) {
return mapUpdater.compareAndSet(owner, this, new FiveAsyncContextMap(keyOne, valueOne, keyTwo, valueTwo,
keyThree, valueThree, keyFour, valueFour, keyFive, valueFive)) ? (T) valueSix : owner.remove(key);
}
return null;
}
@Override
public boolean removeAll(final Iterable<Key<?>> entries, CopyOnWriteAsyncContextMap owner,
AtomicReferenceFieldUpdater<CopyOnWriteAsyncContextMap, CopyAsyncContextMap> mapUpdater) {
assert keyOne != null && keyTwo != null && keyThree != null && keyFour != null && keyFive != null &&
keySix != null;
MutableInt removeIndexMask = new MutableInt();
entries.forEach(k -> {
if (keyOne.equals(k)) {
removeIndexMask.value |= 0x1;
} else if (keyTwo.equals(k)) {
removeIndexMask.value |= 0x2;
} else if (keyThree.equals(k)) {
removeIndexMask.value |= 0x4;
} else if (keyFour.equals(k)) {
removeIndexMask.value |= 0x8;
} else if (keyFive.equals(k)) {
removeIndexMask.value |= 0x10;
} else if (keySix.equals(k)) {
removeIndexMask.value |= 0x20;
}
});
CopyAsyncContextMap newMap = removeAll(removeIndexMask);
if (newMap == null) {
return false;
}
return mapUpdater.compareAndSet(owner, this, newMap) || owner.removeAll(entries);
}
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;
}