Skip to content

Commit 1941eed

Browse files
authored
Added AtomicBuffer compareAndExchange int/long (#334)
1 parent 21d5603 commit 1941eed

File tree

3 files changed

+90
-0
lines changed

3 files changed

+90
-0
lines changed

agrona/src/main/java/org/agrona/concurrent/AtomicBuffer.java

+27
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,19 @@ public interface AtomicBuffer extends MutableDirectBuffer
218218
*/
219219
boolean compareAndSetLong(int index, long expectedValue, long updateValue);
220220

221+
/**
222+
* Atomic compare and exchange of a long given an expected value.
223+
* <p>
224+
* This call has sequential-consistent semantics.
225+
*
226+
* @param index in bytes for where to put.
227+
* @param expectedValue at to be compared.
228+
* @param updateValue to be exchanged.
229+
* @return the old value no matter if the expected value was found.
230+
* @since 2.1.0
231+
*/
232+
long compareAndExchangeLong(int index, long expectedValue, long updateValue);
233+
221234
/**
222235
* Atomically exchange a value at a location returning the previous contents.
223236
* <p>
@@ -359,6 +372,20 @@ public interface AtomicBuffer extends MutableDirectBuffer
359372
*/
360373
boolean compareAndSetInt(int index, int expectedValue, int updateValue);
361374

375+
/**
376+
* Atomic compare and exchange of a int given an expected value.
377+
* <p>
378+
* This call has sequential-consistent semantics.
379+
*
380+
* @param index in bytes for where to put.
381+
* @param expectedValue at to be compared.
382+
* @param updateValue to be exchanged.
383+
* @return the old value no matter if the expected value was found.
384+
* @since 2.1.0
385+
*/
386+
int compareAndExchangeInt(int index, int expectedValue, int updateValue);
387+
388+
362389
/**
363390
* Atomically exchange a value at a location returning the previous contents.
364391
* <p>

agrona/src/main/java/org/agrona/concurrent/UnsafeBuffer.java

+27
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,20 @@ public boolean compareAndSetLong(final int index, final long expectedValue, fina
508508
return UnsafeApi.compareAndSetLong(byteArray, addressOffset + index, expectedValue, updateValue);
509509
}
510510

511+
/**
512+
* {@inheritDoc}
513+
*/
514+
public long compareAndExchangeLong(final int index, final long expectedValue, final long updateValue)
515+
{
516+
if (SHOULD_BOUNDS_CHECK)
517+
{
518+
boundsCheck0(index, SIZE_OF_LONG);
519+
}
520+
521+
return UnsafeApi.compareAndExchangeLong(byteArray, addressOffset + index, expectedValue, updateValue);
522+
}
523+
524+
511525
/**
512526
* {@inheritDoc}
513527
*/
@@ -671,6 +685,19 @@ public boolean compareAndSetInt(final int index, final int expectedValue, final
671685
return UnsafeApi.compareAndSetInt(byteArray, addressOffset + index, expectedValue, updateValue);
672686
}
673687

688+
/**
689+
* {@inheritDoc}
690+
*/
691+
public int compareAndExchangeInt(final int index, final int expectedValue, final int updateValue)
692+
{
693+
if (SHOULD_BOUNDS_CHECK)
694+
{
695+
boundsCheck0(index, SIZE_OF_INT);
696+
}
697+
698+
return UnsafeApi.compareAndExchangeInt(byteArray, addressOffset + index, expectedValue, updateValue);
699+
}
700+
674701
/**
675702
* {@inheritDoc}
676703
*/

agrona/src/test/java/org/agrona/concurrent/AtomicBufferTest.java

+36
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,24 @@ void shouldCompareAndSetLongToNativeBuffer(final ByteBuffer buffer)
139139
assertThat(buffer.getLong(INDEX), is(LONG_VALUE + 1));
140140
}
141141

142+
@ParameterizedTest
143+
@MethodSource("atomicBuffers")
144+
void shouldCompareAndExchangeLongToNativeBuffer(final ByteBuffer buffer)
145+
{
146+
final UnsafeBuffer unsafeBuffer = new UnsafeBuffer(buffer);
147+
148+
buffer.putLong(INDEX, LONG_VALUE);
149+
150+
// success
151+
assertEquals(LONG_VALUE, unsafeBuffer.compareAndExchangeLong(INDEX, LONG_VALUE, LONG_VALUE + 1));
152+
assertEquals(LONG_VALUE + 1, unsafeBuffer.getLongVolatile(INDEX));
153+
154+
// failure
155+
assertEquals(LONG_VALUE + 1,
156+
unsafeBuffer.compareAndExchangeLong(INDEX, LONG_VALUE + 10, 21));
157+
assertEquals(LONG_VALUE + 1, buffer.getLong(INDEX));
158+
}
159+
142160
@ParameterizedTest
143161
@MethodSource("atomicBuffers")
144162
void shouldGetAndSetLongToNativeBuffer(final ByteBuffer buffer)
@@ -251,6 +269,24 @@ void shouldCompareAndSetIntToNativeBuffer(final ByteBuffer buffer)
251269
assertThat(buffer.getInt(INDEX), is(INT_VALUE + 1));
252270
}
253271

272+
@ParameterizedTest
273+
@MethodSource("atomicBuffers")
274+
void shouldCompareAndExchangeIntToNativeBuffer(final ByteBuffer buffer)
275+
{
276+
final UnsafeBuffer unsafeBuffer = new UnsafeBuffer(buffer);
277+
278+
buffer.putInt(INDEX, INT_VALUE);
279+
280+
// success
281+
assertEquals(INT_VALUE, unsafeBuffer.compareAndExchangeInt(INDEX, INT_VALUE, INT_VALUE + 1));
282+
assertEquals(INT_VALUE + 1, unsafeBuffer.getIntVolatile(INDEX));
283+
284+
// failure
285+
assertEquals(INT_VALUE + 1,
286+
unsafeBuffer.compareAndExchangeInt(INDEX, INT_VALUE + 10, 21));
287+
assertEquals(INT_VALUE + 1, buffer.getInt(INDEX));
288+
}
289+
254290
@ParameterizedTest
255291
@MethodSource("atomicBuffers")
256292
void shouldGetAndSetIntToNativeBuffer(final ByteBuffer buffer)

0 commit comments

Comments
 (0)