DATAREDIS-874 - Implement accumulate/update methods on RedisAtomic[*] classes.
This commit adds the following public methods to RedisAtomicInteger, RedisAtomicLong, and RedisAtomicDouble: T accumulateAndGet(T updateValue, BinaryOperator<T> accumulatorFunction); T getAndAccumulate(T updateValue, BinaryOperator<T> accumulatorFunction); T updateAndGet(UnaryOperator<T> updateFunction); T getAndUpdate(UnaryOperator<T> updateFunction); These methods are primarily useful for doing CAS operations with the help of Binary/UnaryOperators to generate the new value. They mirror their counterparts on the AtomicInteger and AtomicLong classes available in the java.util.concurrent.atomic package. Original pull request: #362.
This commit is contained in:
committed by
Mark Paluch
parent
7ab8ade8d3
commit
f2107ef81b
@@ -18,6 +18,8 @@ package org.springframework.data.redis.support.atomic;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.DoubleUnaryOperator;
|
||||
import java.util.function.DoubleBinaryOperator;
|
||||
|
||||
import org.springframework.dao.DataRetrievalFailureException;
|
||||
import org.springframework.data.redis.connection.DataType;
|
||||
@@ -39,6 +41,7 @@ import org.springframework.util.Assert;
|
||||
* @author Thomas Darimont
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @author Graham MacMaster
|
||||
*/
|
||||
public class RedisAtomicDouble extends Number implements Serializable, BoundKeyOperations<String> {
|
||||
|
||||
@@ -218,6 +221,44 @@ public class RedisAtomicDouble extends Number implements Serializable, BoundKeyO
|
||||
return addAndGet(delta) - delta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically update the current value using the given update function.
|
||||
*
|
||||
* @param updateFunction the function which calculates the value to set. Should be a pure function (no side effects),
|
||||
* because it will be applied several times if update attempts fail due to concurrent calls.
|
||||
* @return the previous value.
|
||||
*/
|
||||
public double getAndUpdate(DoubleUnaryOperator updateFunction) {
|
||||
|
||||
double previousValue, newValue;
|
||||
do {
|
||||
previousValue = get();
|
||||
newValue = updateFunction.applyAsDouble(previousValue);
|
||||
} while (!compareAndSet(previousValue, newValue));
|
||||
return previousValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically update the current value using the given accumulator function.
|
||||
* The new value is calculated by applying the accumulator function to the current value and the
|
||||
* given `updateValue`.
|
||||
*
|
||||
* @param updateValue the value which will be passed into the accumulator function.
|
||||
* @param accumulatorFunction the function which calculates the value to set. Should be a pure function (no side
|
||||
* effects), because it will be applied several times if update attempts fail due to
|
||||
* concurrent calls.
|
||||
* @return the previous value.
|
||||
*/
|
||||
public double getAndAccumulate(double updateValue, DoubleBinaryOperator accumulatorFunction) {
|
||||
|
||||
double previousValue, newValue;
|
||||
do {
|
||||
previousValue = get();
|
||||
newValue = accumulatorFunction.applyAsDouble(previousValue, updateValue);
|
||||
} while (!compareAndSet(previousValue, newValue));
|
||||
return previousValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically increments by one the current value.
|
||||
*
|
||||
@@ -246,6 +287,44 @@ public class RedisAtomicDouble extends Number implements Serializable, BoundKeyO
|
||||
return operations.increment(key, delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically update the current value using the given update function.
|
||||
*
|
||||
* @param updateFunction the function which calculates the value to set. Should be a pure function (no side effects),
|
||||
* because it will be applied several times if update attempts fail due to concurrent calls.
|
||||
* @return the updated value.
|
||||
*/
|
||||
public double updateAndGet(DoubleUnaryOperator updateFunction) {
|
||||
|
||||
double previousValue, newValue;
|
||||
do {
|
||||
previousValue = get();
|
||||
newValue = updateFunction.applyAsDouble(previousValue);
|
||||
} while (!compareAndSet(previousValue, newValue));
|
||||
return newValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically update the current value using the given accumulator function.
|
||||
* The new value is calculated by applying the accumulator function to the current value and the
|
||||
* given `updateValue`.
|
||||
*
|
||||
* @param updateValue the value which will be passed into the accumulator function.
|
||||
* @param accumulatorFunction the function which calculates the value to set. Should be a pure function (no side
|
||||
* effects), because it will be applied several times if update attempts fail due to
|
||||
* concurrent calls.
|
||||
* @return the updated value.
|
||||
*/
|
||||
public double accumulateAndGet(double updateValue, DoubleBinaryOperator accumulatorFunction) {
|
||||
|
||||
double previousValue, newValue;
|
||||
do {
|
||||
previousValue = get();
|
||||
newValue = accumulatorFunction.applyAsDouble(previousValue, updateValue);
|
||||
} while (!compareAndSet(previousValue, newValue));
|
||||
return newValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the String representation of the current value.
|
||||
*/
|
||||
|
||||
@@ -18,6 +18,8 @@ package org.springframework.data.redis.support.atomic;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.IntBinaryOperator;
|
||||
import java.util.function.IntUnaryOperator;
|
||||
|
||||
import org.springframework.dao.DataRetrievalFailureException;
|
||||
import org.springframework.data.redis.connection.DataType;
|
||||
@@ -39,6 +41,7 @@ import org.springframework.util.Assert;
|
||||
* @author Thomas Darimont
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @author Graham MacMaster
|
||||
* @see java.util.concurrent.atomic.AtomicInteger
|
||||
*/
|
||||
public class RedisAtomicInteger extends Number implements Serializable, BoundKeyOperations<String> {
|
||||
@@ -216,6 +219,44 @@ public class RedisAtomicInteger extends Number implements Serializable, BoundKey
|
||||
return addAndGet(delta) - delta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically update the current value using the given update function.
|
||||
*
|
||||
* @param updateFunction the function which calculates the value to set. Should be a pure function (no side effects),
|
||||
* because it will be applied several times if update attempts fail due to concurrent calls.
|
||||
* @return the previous value.
|
||||
*/
|
||||
public int getAndUpdate(IntUnaryOperator updateFunction) {
|
||||
|
||||
int previousValue, newValue;
|
||||
do {
|
||||
previousValue = get();
|
||||
newValue = updateFunction.applyAsInt(previousValue);
|
||||
} while (!compareAndSet(previousValue, newValue));
|
||||
return previousValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically update the current value using the given accumulator function.
|
||||
* The new value is calculated by applying the accumulator function to the current value and the
|
||||
* given `updateValue`.
|
||||
*
|
||||
* @param updateValue the value which will be passed into the accumulator function.
|
||||
* @param accumulatorFunction the function which calculates the value to set. Should be a pure function (no side
|
||||
* effects), because it will be applied several times if update attempts fail due to
|
||||
* concurrent calls.
|
||||
* @return the previous value.
|
||||
*/
|
||||
public int getAndAccumulate(int updateValue, IntBinaryOperator accumulatorFunction) {
|
||||
|
||||
int previousValue, newValue;
|
||||
do {
|
||||
previousValue = get();
|
||||
newValue = accumulatorFunction.applyAsInt(previousValue, updateValue);
|
||||
} while (!compareAndSet(previousValue, newValue));
|
||||
return previousValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically increment by one the current value.
|
||||
*
|
||||
@@ -244,6 +285,44 @@ public class RedisAtomicInteger extends Number implements Serializable, BoundKey
|
||||
return operations.increment(key, delta).intValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically update the current value using the given update function.
|
||||
*
|
||||
* @param updateFunction the function which calculates the value to set. Should be a pure function (no side effects),
|
||||
* because it will be applied several times if update attempts fail due to concurrent calls.
|
||||
* @return the updated value.
|
||||
*/
|
||||
public int updateAndGet(IntUnaryOperator updateFunction) {
|
||||
|
||||
int previousValue, newValue;
|
||||
do {
|
||||
previousValue = get();
|
||||
newValue = updateFunction.applyAsInt(previousValue);
|
||||
} while (!compareAndSet(previousValue, newValue));
|
||||
return newValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically update the current value using the given accumulator function.
|
||||
* The new value is calculated by applying the accumulator function to the current value and the
|
||||
* given `updateValue`.
|
||||
*
|
||||
* @param updateValue the value which will be passed into the accumulator function.
|
||||
* @param accumulatorFunction the function which calculates the value to set. Should be a pure function (no side
|
||||
* effects), because it will be applied several times if update attempts fail due to
|
||||
* concurrent calls.
|
||||
* @return the updated value.
|
||||
*/
|
||||
public int accumulateAndGet(int updateValue, IntBinaryOperator accumulatorFunction) {
|
||||
|
||||
int previousValue, newValue;
|
||||
do {
|
||||
previousValue = get();
|
||||
newValue = accumulatorFunction.applyAsInt(previousValue, updateValue);
|
||||
} while (!compareAndSet(previousValue, newValue));
|
||||
return newValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the String representation of the current value.
|
||||
*/
|
||||
|
||||
@@ -18,6 +18,8 @@ package org.springframework.data.redis.support.atomic;
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.LongBinaryOperator;
|
||||
import java.util.function.LongUnaryOperator;
|
||||
|
||||
import org.springframework.dao.DataRetrievalFailureException;
|
||||
import org.springframework.data.redis.connection.DataType;
|
||||
@@ -40,6 +42,7 @@ import org.springframework.util.Assert;
|
||||
* @author Thomas Darimont
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @author Graham MacMaster
|
||||
* @see java.util.concurrent.atomic.AtomicLong
|
||||
*/
|
||||
public class RedisAtomicLong extends Number implements Serializable, BoundKeyOperations<String> {
|
||||
@@ -223,6 +226,44 @@ public class RedisAtomicLong extends Number implements Serializable, BoundKeyOpe
|
||||
return addAndGet(delta) - delta;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically update the current value using the given update function.
|
||||
*
|
||||
* @param updateFunction the function which calculates the value to set. Should be a pure function (no side effects),
|
||||
* because it will be applied several times if update attempts fail due to concurrent calls.
|
||||
* @return the previous value.
|
||||
*/
|
||||
public long getAndUpdate(LongUnaryOperator updateFunction) {
|
||||
|
||||
long previousValue, newValue;
|
||||
do {
|
||||
previousValue = get();
|
||||
newValue = updateFunction.applyAsLong(previousValue);
|
||||
} while (!compareAndSet(previousValue, newValue));
|
||||
return previousValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically update the current value using the given accumulator function.
|
||||
* The new value is calculated by applying the accumulator function to the current value and the
|
||||
* given `updateValue`.
|
||||
*
|
||||
* @param updateValue the value which will be passed into the accumulator function.
|
||||
* @param accumulatorFunction the function which calculates the value to set. Should be a pure function (no side
|
||||
* effects), because it will be applied several times if update attempts fail due to
|
||||
* concurrent calls.
|
||||
* @return the previous value.
|
||||
*/
|
||||
public long getAndAccumulate(long updateValue, LongBinaryOperator accumulatorFunction) {
|
||||
|
||||
long previousValue, newValue;
|
||||
do {
|
||||
previousValue = get();
|
||||
newValue = accumulatorFunction.applyAsLong(previousValue, updateValue);
|
||||
} while (!compareAndSet(previousValue, newValue));
|
||||
return previousValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically increments by one the current value.
|
||||
*
|
||||
@@ -251,6 +292,44 @@ public class RedisAtomicLong extends Number implements Serializable, BoundKeyOpe
|
||||
return operations.increment(key, delta);
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically update the current value using the given update function.
|
||||
*
|
||||
* @param updateFunction the function which calculates the value to set. Should be a pure function (no side effects),
|
||||
* because it will be applied several times if update attempts fail due to concurrent calls.
|
||||
* @return the updated value.
|
||||
*/
|
||||
public long updateAndGet(LongUnaryOperator updateFunction) {
|
||||
|
||||
long previousValue, newValue;
|
||||
do {
|
||||
previousValue = get();
|
||||
newValue = updateFunction.applyAsLong(previousValue);
|
||||
} while (!compareAndSet(previousValue, newValue));
|
||||
return newValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* Atomically update the current value using the given accumulator function.
|
||||
* The new value is calculated by applying the accumulator function to the current value and the
|
||||
* given `updateValue`.
|
||||
*
|
||||
* @param updateValue the value which will be passed into the accumulator function.
|
||||
* @param accumulatorFunction the function which calculates the value to set. Should be a pure function (no side
|
||||
* effects), because it will be applied several times if update attempts fail due to
|
||||
* concurrent calls.
|
||||
* @return the updated value.
|
||||
*/
|
||||
public long accumulateAndGet(long updateValue, LongBinaryOperator accumulatorFunction) {
|
||||
|
||||
long previousValue, newValue;
|
||||
do {
|
||||
previousValue = get();
|
||||
newValue = accumulatorFunction.applyAsLong(previousValue, updateValue);
|
||||
} while (!compareAndSet(previousValue, newValue));
|
||||
return newValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the String representation of the current value.
|
||||
*/
|
||||
|
||||
@@ -20,6 +20,9 @@ import static org.assertj.core.api.Assertions.*;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.DoubleUnaryOperator;
|
||||
import java.util.function.DoubleBinaryOperator;
|
||||
|
||||
import org.assertj.core.data.Offset;
|
||||
import org.junit.After;
|
||||
@@ -43,6 +46,7 @@ import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
* @author Thomas Darimont
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @author Graham MacMaster
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public class RedisAtomicDoubleTests extends AbstractRedisAtomicsTests {
|
||||
@@ -225,4 +229,96 @@ public class RedisAtomicDoubleTests extends AbstractRedisAtomicsTests {
|
||||
|
||||
assertThat(test.getAndSet(2)).isZero();
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-874
|
||||
public void updateAndGetAppliesGivenUpdateFunctionAndReturnsUpdatedValue() {
|
||||
|
||||
// Arrange
|
||||
AtomicBoolean operatorHasBeenApplied = new AtomicBoolean(false);
|
||||
double initialValue = 5.3;
|
||||
double expectedNewValue = 10.6;
|
||||
doubleCounter.set(initialValue);
|
||||
|
||||
DoubleUnaryOperator updateFunction = input -> {
|
||||
operatorHasBeenApplied.set(true);
|
||||
return expectedNewValue;
|
||||
};
|
||||
|
||||
// Act
|
||||
double result = doubleCounter.updateAndGet(updateFunction);
|
||||
|
||||
// Assert
|
||||
assertThat(result).isEqualTo(expectedNewValue);
|
||||
assertThat(doubleCounter.get()).isEqualTo(expectedNewValue);
|
||||
assertThat(operatorHasBeenApplied.get()).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-874
|
||||
public void getAndUpdateAppliesGivenUpdateFunctionAndReturnsOriginalValue() {
|
||||
|
||||
// Arrange
|
||||
AtomicBoolean operatorHasBeenApplied = new AtomicBoolean(false);
|
||||
double initialValue = 5.3;
|
||||
double expectedNewValue = 10.6;
|
||||
doubleCounter.set(initialValue);
|
||||
|
||||
DoubleUnaryOperator updateFunction = input -> {
|
||||
operatorHasBeenApplied.set(true);
|
||||
return expectedNewValue;
|
||||
};
|
||||
|
||||
// Act
|
||||
double result = doubleCounter.getAndUpdate(updateFunction);
|
||||
|
||||
// Assert
|
||||
assertThat(result).isEqualTo(initialValue);
|
||||
assertThat(doubleCounter.get()).isEqualTo(expectedNewValue);
|
||||
assertThat(operatorHasBeenApplied.get()).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-874
|
||||
public void accumulateAndGetAppliesGivenAccumulatorFunctionAndReturnsUpdatedValue() {
|
||||
|
||||
// Arrange
|
||||
AtomicBoolean operatorHasBeenApplied = new AtomicBoolean(false);
|
||||
double initialValue = 5.3;
|
||||
double expectedNewValue = 10.6;
|
||||
doubleCounter.set(initialValue);
|
||||
|
||||
DoubleBinaryOperator accumulatorFunction = (x, y) -> {
|
||||
operatorHasBeenApplied.set(true);
|
||||
return expectedNewValue;
|
||||
};
|
||||
|
||||
// Act
|
||||
double result = doubleCounter.accumulateAndGet(15.9, accumulatorFunction);
|
||||
|
||||
// Assert
|
||||
assertThat(result).isEqualTo(expectedNewValue);
|
||||
assertThat(doubleCounter.get()).isEqualTo(expectedNewValue);
|
||||
assertThat(operatorHasBeenApplied.get()).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-874
|
||||
public void getAndAccumulateAppliesGivenAccumulatorFunctionAndReturnsOriginalValue() {
|
||||
|
||||
// Arrange
|
||||
AtomicBoolean operatorHasBeenApplied = new AtomicBoolean(false);
|
||||
double initialValue = 5.3;
|
||||
double expectedNewValue = 10.6;
|
||||
doubleCounter.set(initialValue);
|
||||
|
||||
DoubleBinaryOperator accumulatorFunction = (x, y) -> {
|
||||
operatorHasBeenApplied.set(true);
|
||||
return expectedNewValue;
|
||||
};
|
||||
|
||||
// Act
|
||||
double result = doubleCounter.getAndAccumulate(15.9, accumulatorFunction);
|
||||
|
||||
// Assert
|
||||
assertThat(result).isEqualTo(initialValue);
|
||||
assertThat(doubleCounter.get()).isEqualTo(expectedNewValue);
|
||||
assertThat(operatorHasBeenApplied.get()).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ import static org.assertj.core.api.Assertions.*;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.IntBinaryOperator;
|
||||
import java.util.function.IntUnaryOperator;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
@@ -43,6 +45,7 @@ import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
* @author Thomas Darimont
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @author Graham MacMaster
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public class RedisAtomicIntegerTests extends AbstractRedisAtomicsTests {
|
||||
@@ -233,4 +236,96 @@ public class RedisAtomicIntegerTests extends AbstractRedisAtomicsTests {
|
||||
|
||||
assertThat(test.getAndSet(2)).isZero();
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-874
|
||||
public void updateAndGetAppliesGivenUpdateFunctionAndReturnsUpdatedValue() {
|
||||
|
||||
// Arrange
|
||||
AtomicBoolean operatorHasBeenApplied = new AtomicBoolean(false);
|
||||
int initialValue = 5;
|
||||
int expectedNewValue = 10;
|
||||
intCounter.set(initialValue);
|
||||
|
||||
IntUnaryOperator updateFunction = input -> {
|
||||
operatorHasBeenApplied.set(true);
|
||||
return expectedNewValue;
|
||||
};
|
||||
|
||||
// Act
|
||||
int result = intCounter.updateAndGet(updateFunction);
|
||||
|
||||
// Assert
|
||||
assertThat(result).isEqualTo(expectedNewValue);
|
||||
assertThat(intCounter.get()).isEqualTo(expectedNewValue);
|
||||
assertThat(operatorHasBeenApplied.get()).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-874
|
||||
public void getAndUpdateAppliesGivenUpdateFunctionAndReturnsOriginalValue() {
|
||||
|
||||
// Arrange
|
||||
AtomicBoolean operatorHasBeenApplied = new AtomicBoolean(false);
|
||||
int initialValue = 5;
|
||||
int expectedNewValue = 10;
|
||||
intCounter.set(initialValue);
|
||||
|
||||
IntUnaryOperator updateFunction = input -> {
|
||||
operatorHasBeenApplied.set(true);
|
||||
return expectedNewValue;
|
||||
};
|
||||
|
||||
// Act
|
||||
int result = intCounter.getAndUpdate(updateFunction);
|
||||
|
||||
// Assert
|
||||
assertThat(result).isEqualTo(initialValue);
|
||||
assertThat(intCounter.get()).isEqualTo(expectedNewValue);
|
||||
assertThat(operatorHasBeenApplied.get()).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-874
|
||||
public void accumulateAndGetAppliesGivenAccumulatorFunctionAndReturnsUpdatedValue() {
|
||||
|
||||
// Arrange
|
||||
AtomicBoolean operatorHasBeenApplied = new AtomicBoolean(false);
|
||||
int initialValue = 5;
|
||||
int expectedNewValue = 10;
|
||||
intCounter.set(initialValue);
|
||||
|
||||
IntBinaryOperator accumulatorFunction = (x, y) -> {
|
||||
operatorHasBeenApplied.set(true);
|
||||
return expectedNewValue;
|
||||
};
|
||||
|
||||
// Act
|
||||
int result = intCounter.accumulateAndGet(15, accumulatorFunction);
|
||||
|
||||
// Assert
|
||||
assertThat(result).isEqualTo(expectedNewValue);
|
||||
assertThat(intCounter.get()).isEqualTo(expectedNewValue);
|
||||
assertThat(operatorHasBeenApplied.get()).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-874
|
||||
public void getAndAccumulateAppliesGivenAccumulatorFunctionAndReturnsOriginalValue() {
|
||||
|
||||
// Arrange
|
||||
AtomicBoolean operatorHasBeenApplied = new AtomicBoolean(false);
|
||||
int initialValue = 5;
|
||||
int expectedNewValue = 10;
|
||||
intCounter.set(initialValue);
|
||||
|
||||
IntBinaryOperator accumulatorFunction = (x, y) -> {
|
||||
operatorHasBeenApplied.set(true);
|
||||
return expectedNewValue;
|
||||
};
|
||||
|
||||
// Act
|
||||
int result = intCounter.getAndAccumulate(15, accumulatorFunction);
|
||||
|
||||
// Assert
|
||||
assertThat(result).isEqualTo(initialValue);
|
||||
assertThat(intCounter.get()).isEqualTo(expectedNewValue);
|
||||
assertThat(operatorHasBeenApplied.get()).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,9 @@ package org.springframework.data.redis.support.atomic;
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
import java.util.function.LongBinaryOperator;
|
||||
import java.util.function.LongUnaryOperator;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
@@ -41,6 +44,7 @@ import org.springframework.data.redis.serializer.StringRedisSerializer;
|
||||
* @author Thomas Darimont
|
||||
* @author Christoph Strobl
|
||||
* @author Mark Paluch
|
||||
* @author Graham MacMaster
|
||||
*/
|
||||
@RunWith(Parameterized.class)
|
||||
public class RedisAtomicLongTests extends AbstractRedisAtomicsTests {
|
||||
@@ -214,4 +218,96 @@ public class RedisAtomicLongTests extends AbstractRedisAtomicsTests {
|
||||
|
||||
assertThat(test.getAndSet(2)).isZero();
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-874
|
||||
public void updateAndGetAppliesGivenUpdateFunctionAndReturnsUpdatedValue() {
|
||||
|
||||
// Arrange
|
||||
AtomicBoolean operatorHasBeenApplied = new AtomicBoolean(false);
|
||||
long initialValue = 5;
|
||||
long expectedNewValue = 10;
|
||||
longCounter.set(initialValue);
|
||||
|
||||
LongUnaryOperator updateFunction = input -> {
|
||||
operatorHasBeenApplied.set(true);
|
||||
return expectedNewValue;
|
||||
};
|
||||
|
||||
// Act
|
||||
long result = longCounter.updateAndGet(updateFunction);
|
||||
|
||||
// Assert
|
||||
assertThat(result).isEqualTo(expectedNewValue);
|
||||
assertThat(longCounter.get()).isEqualTo(expectedNewValue);
|
||||
assertThat(operatorHasBeenApplied.get()).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-874
|
||||
public void getAndUpdateAppliesGivenUpdateFunctionAndReturnsOriginalValue() {
|
||||
|
||||
// Arrange
|
||||
AtomicBoolean operatorHasBeenApplied = new AtomicBoolean(false);
|
||||
long initialValue = 5;
|
||||
long expectedNewValue = 10;
|
||||
longCounter.set(initialValue);
|
||||
|
||||
LongUnaryOperator updateFunction = input -> {
|
||||
operatorHasBeenApplied.set(true);
|
||||
return expectedNewValue;
|
||||
};
|
||||
|
||||
// Act
|
||||
long result = longCounter.getAndUpdate(updateFunction);
|
||||
|
||||
// Assert
|
||||
assertThat(result).isEqualTo(initialValue);
|
||||
assertThat(longCounter.get()).isEqualTo(expectedNewValue);
|
||||
assertThat(operatorHasBeenApplied.get()).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-874
|
||||
public void accumulateAndGetAppliesGivenAccumulatorFunctionAndReturnsUpdatedValue() {
|
||||
|
||||
// Arrange
|
||||
AtomicBoolean operatorHasBeenApplied = new AtomicBoolean(false);
|
||||
long initialValue = 5;
|
||||
long expectedNewValue = 10;
|
||||
longCounter.set(initialValue);
|
||||
|
||||
LongBinaryOperator accumulatorFunction = (x, y) -> {
|
||||
operatorHasBeenApplied.set(true);
|
||||
return expectedNewValue;
|
||||
};
|
||||
|
||||
// Act
|
||||
long result = longCounter.accumulateAndGet(15L, accumulatorFunction);
|
||||
|
||||
// Assert
|
||||
assertThat(result).isEqualTo(expectedNewValue);
|
||||
assertThat(longCounter.get()).isEqualTo(expectedNewValue);
|
||||
assertThat(operatorHasBeenApplied.get()).isTrue();
|
||||
}
|
||||
|
||||
@Test // DATAREDIS-874
|
||||
public void getAndAccumulateAppliesGivenAccumulatorFunctionAndReturnsOriginalValue() {
|
||||
|
||||
// Arrange
|
||||
AtomicBoolean operatorHasBeenApplied = new AtomicBoolean(false);
|
||||
long initialValue = 5;
|
||||
long expectedNewValue = 10;
|
||||
longCounter.set(initialValue);
|
||||
|
||||
LongBinaryOperator accumulatorFunction = (x, y) -> {
|
||||
operatorHasBeenApplied.set(true);
|
||||
return expectedNewValue;
|
||||
};
|
||||
|
||||
// Act
|
||||
long result = longCounter.getAndAccumulate(15L, accumulatorFunction);
|
||||
|
||||
// Assert
|
||||
assertThat(result).isEqualTo(initialValue);
|
||||
assertThat(longCounter.get()).isEqualTo(expectedNewValue);
|
||||
assertThat(operatorHasBeenApplied.get()).isTrue();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user