Class UnsafeBuffer
- java.lang.Object
-
- org.agrona.AbstractMutableDirectBuffer
-
- org.agrona.concurrent.UnsafeBuffer
-
- All Implemented Interfaces:
java.lang.Comparable<DirectBuffer>
,AtomicBuffer
,DirectBuffer
,MutableDirectBuffer
public class UnsafeBuffer extends AbstractMutableDirectBuffer implements AtomicBuffer
Supports regular, byte ordered, and atomic (memory ordered) access to an underlying buffer. The buffer can be a byte[], one of the variousByteBuffer
implementations, or an off Java heap memory address.ByteOrder
of a wrapped buffer is not applied to theUnsafeBuffer
.UnsafeBuffer
s are effectively stateless and can be used concurrently, the wrapping methods are an exception. To controlByteOrder
use the appropriate method with theByteOrder
overload.Note: This class has a natural ordering that is inconsistent with equals. Types may be different but equal on buffer contents.
Note: The wrap methods on this class are not thread safe. Concurrent access should only happen after a successful wrap.
-
-
Field Summary
Fields Modifier and Type Field Description static int
ALIGNMENT
private java.nio.ByteBuffer
byteBuffer
static java.lang.String
DISABLE_BOUNDS_CHECKS_PROP_NAME
static boolean
SHOULD_BOUNDS_CHECK
private int
wrapAdjustment
-
Fields inherited from class org.agrona.AbstractMutableDirectBuffer
addressOffset, byteArray, capacity
-
Fields inherited from interface org.agrona.concurrent.AtomicBuffer
STRICT_ALIGNMENT_CHECKS, STRICT_ALIGNMENT_CHECKS_PROP_NAME
-
Fields inherited from interface org.agrona.DirectBuffer
DISABLE_ARRAY_CONTENT_PRINTOUT_PROP_NAME, STR_HEADER_LEN
-
-
Constructor Summary
Constructors Constructor Description UnsafeBuffer()
Empty constructor for a reusable wrapper buffer.UnsafeBuffer(byte[] buffer)
Attach a view to abyte[]
for providing direct access.UnsafeBuffer(byte[] buffer, int offset, int length)
Attach a view to abyte[]
for providing direct access.UnsafeBuffer(long address, int length)
Attach a view to an off-heap memory region by address.UnsafeBuffer(java.nio.ByteBuffer buffer)
Attach a view to aByteBuffer
for providing direct access, theByteBuffer
can be heap based or direct.UnsafeBuffer(java.nio.ByteBuffer buffer, int offset, int length)
Attach a view to aByteBuffer
for providing direct access, theByteBuffer
can be heap based or direct.UnsafeBuffer(DirectBuffer buffer)
Attach a view to an existingDirectBuffer
UnsafeBuffer(DirectBuffer buffer, int offset, int length)
Attach a view to an existingDirectBuffer
-
Method Summary
All Methods Static Methods Instance Methods Concrete Methods Modifier and Type Method Description int
addIntOrdered(int index, int increment)
Add a value to a given index with ordered store semantics.long
addLongOrdered(int index, long increment)
Add a value to a given index with ordered store semantics.private static void
boundsCheckWrap(int offset, int length, int capacity)
java.nio.ByteBuffer
byteBuffer()
Get the underlyingByteBuffer
if one exists.boolean
compareAndSetInt(int index, int expectedValue, int updateValue)
Atomic compare and set of an int given an expected value.boolean
compareAndSetLong(int index, long expectedValue, long updateValue)
Atomic compare and set of a long given an expected value.protected void
ensureCapacity(int index, int length)
int
getAndAddInt(int index, int delta)
Atomically add a delta to a value at a location returning the previous contents.long
getAndAddLong(int index, long delta)
Atomically add a delta to a value at a location returning the previous contents.int
getAndSetInt(int index, int value)
Atomically exchange a value at a location returning the previous contents.long
getAndSetLong(int index, long value)
Atomically exchange a value at a location returning the previous contents.byte
getByteVolatile(int index)
Get the value at a given index with volatile semantics.char
getCharVolatile(int index)
Get the value at a given index with volatile semantics.int
getIntVolatile(int index)
Get the value at a given index with volatile semantics.long
getLongVolatile(int index)
Get the value at a given index with volatile semantics.short
getShortVolatile(int index)
Get the value at a given index with volatile semantics.boolean
isExpandable()
Is this buffer expandable to accommodate putting data into it beyond the current capacity?void
putByteVolatile(int index, byte value)
Put a value to a given index with volatile semantics.void
putCharVolatile(int index, char value)
Put a value to a given index with volatile semantics.void
putIntOrdered(int index, int value)
Put a value to a given index with ordered semantics.void
putIntVolatile(int index, int value)
Put a value to a given index with volatile semantics.void
putLongOrdered(int index, long value)
Put a value to a given index with ordered store semantics.void
putLongVolatile(int index, long value)
Put a value to a given index with volatile semantics.void
putShortVolatile(int index, short value)
Put a value to a given index with volatile semantics.java.lang.String
toString()
void
verifyAlignment()
Verify that the underlying buffer is correctly aligned to prevent word tearing, other ordering issues and the JVM crashes.void
wrap(byte[] buffer)
Attach a view to abyte[]
for providing direct access.void
wrap(byte[] buffer, int offset, int length)
Attach a view to abyte[]
for providing direct access.void
wrap(long address, int length)
Attach a view to an off-heap memory region by address.void
wrap(java.nio.ByteBuffer buffer)
Attach a view to aByteBuffer
for providing direct access, theByteBuffer
can be heap based or direct.void
wrap(java.nio.ByteBuffer buffer, int offset, int length)
Attach a view to aByteBuffer
for providing direct access.void
wrap(DirectBuffer buffer)
Attach a view to an existingDirectBuffer
void
wrap(DirectBuffer buffer, int offset, int length)
Attach a view to aDirectBuffer
for providing direct access.int
wrapAdjustment()
Get the adjustment in indices between an index in this buffer and the wrapped object.-
Methods inherited from class org.agrona.AbstractMutableDirectBuffer
addressOffset, boundsCheck, boundsCheck0, byteArray, capacity, checkLimit, compareTo, equals, getByte, getBytes, getBytes, getBytes, getBytes, getBytes, getChar, getChar, getDouble, getDouble, getFloat, getFloat, getInt, getInt, getLong, getLong, getShort, getShort, getStringAscii, getStringAscii, getStringAscii, getStringAscii, getStringAscii, getStringAscii, getStringUtf8, getStringUtf8, getStringUtf8, getStringWithoutLengthAscii, getStringWithoutLengthAscii, getStringWithoutLengthUtf8, hashCode, parseIntAscii, parseLongAscii, parseNaturalIntAscii, parseNaturalLongAscii, putByte, putBytes, putBytes, putBytes, putBytes, putBytes, putChar, putChar, putDouble, putDouble, putFloat, putFloat, putInt, putInt, putIntAscii, putLong, putLong, putLongAscii, putNaturalIntAscii, putNaturalIntAsciiFromEnd, putNaturalLongAscii, putNaturalPaddedIntAscii, putShort, putShort, putStringAscii, putStringAscii, putStringAscii, putStringAscii, putStringUtf8, putStringUtf8, putStringUtf8, putStringUtf8, putStringWithoutLengthAscii, putStringWithoutLengthAscii, putStringWithoutLengthAscii, putStringWithoutLengthAscii, putStringWithoutLengthUtf8, setMemory
-
Methods inherited from class java.lang.Object
clone, finalize, getClass, notify, notifyAll, wait, wait, wait
-
Methods inherited from interface org.agrona.DirectBuffer
addressOffset, boundsCheck, byteArray, capacity, checkLimit, getByte, getBytes, getBytes, getBytes, getBytes, getBytes, getChar, getChar, getDouble, getDouble, getFloat, getFloat, getInt, getInt, getLong, getLong, getShort, getShort, getStringAscii, getStringAscii, getStringAscii, getStringAscii, getStringAscii, getStringAscii, getStringUtf8, getStringUtf8, getStringUtf8, getStringWithoutLengthAscii, getStringWithoutLengthAscii, getStringWithoutLengthUtf8, parseIntAscii, parseLongAscii, parseNaturalIntAscii, parseNaturalLongAscii
-
Methods inherited from interface org.agrona.MutableDirectBuffer
putByte, putBytes, putBytes, putBytes, putBytes, putBytes, putChar, putChar, putDouble, putDouble, putFloat, putFloat, putInt, putInt, putIntAscii, putLong, putLong, putLongAscii, putNaturalIntAscii, putNaturalIntAsciiFromEnd, putNaturalLongAscii, putNaturalPaddedIntAscii, putShort, putShort, putStringAscii, putStringAscii, putStringAscii, putStringAscii, putStringUtf8, putStringUtf8, putStringUtf8, putStringUtf8, putStringWithoutLengthAscii, putStringWithoutLengthAscii, putStringWithoutLengthAscii, putStringWithoutLengthAscii, putStringWithoutLengthUtf8, setMemory
-
-
-
-
Field Detail
-
ALIGNMENT
public static final int ALIGNMENT
- See Also:
AtomicBuffer.ALIGNMENT
, Constant Field Values
-
DISABLE_BOUNDS_CHECKS_PROP_NAME
public static final java.lang.String DISABLE_BOUNDS_CHECKS_PROP_NAME
-
SHOULD_BOUNDS_CHECK
public static final boolean SHOULD_BOUNDS_CHECK
- See Also:
DirectBuffer.SHOULD_BOUNDS_CHECK
-
byteBuffer
private java.nio.ByteBuffer byteBuffer
-
wrapAdjustment
private int wrapAdjustment
-
-
Constructor Detail
-
UnsafeBuffer
public UnsafeBuffer()
Empty constructor for a reusable wrapper buffer.
-
UnsafeBuffer
public UnsafeBuffer(byte[] buffer)
Attach a view to abyte[]
for providing direct access.- Parameters:
buffer
- to which the view is attached.- See Also:
wrap(byte[])
-
UnsafeBuffer
public UnsafeBuffer(byte[] buffer, int offset, int length)
Attach a view to abyte[]
for providing direct access.- Parameters:
buffer
- to which the view is attached.offset
- in bytes within the buffer to begin.length
- in bytes of the buffer included in the view.- See Also:
wrap(byte[], int, int)
-
UnsafeBuffer
public UnsafeBuffer(java.nio.ByteBuffer buffer)
Attach a view to aByteBuffer
for providing direct access, theByteBuffer
can be heap based or direct.- Parameters:
buffer
- to which the view is attached.
-
UnsafeBuffer
public UnsafeBuffer(java.nio.ByteBuffer buffer, int offset, int length)
Attach a view to aByteBuffer
for providing direct access, theByteBuffer
can be heap based or direct.- Parameters:
buffer
- to which the view is attached.offset
- in bytes within the buffer to begin.length
- in bytes of the buffer included in the view.
-
UnsafeBuffer
public UnsafeBuffer(DirectBuffer buffer)
Attach a view to an existingDirectBuffer
- Parameters:
buffer
- to which the view is attached.
-
UnsafeBuffer
public UnsafeBuffer(DirectBuffer buffer, int offset, int length)
Attach a view to an existingDirectBuffer
- Parameters:
buffer
- to which the view is attached.offset
- in bytes within the buffer to begin.length
- in bytes of the buffer included in the view.
-
UnsafeBuffer
public UnsafeBuffer(long address, int length)
Attach a view to an off-heap memory region by address. This is useful for interacting with native libraries.- Parameters:
address
- where the memory begins off-heaplength
- of the buffer from the given address
-
-
Method Detail
-
wrap
public void wrap(byte[] buffer)
Attach a view to abyte[]
for providing direct access.- Specified by:
wrap
in interfaceDirectBuffer
- Parameters:
buffer
- to which the view is attached.
-
wrap
public void wrap(byte[] buffer, int offset, int length)
Attach a view to abyte[]
for providing direct access.- Specified by:
wrap
in interfaceDirectBuffer
- Parameters:
buffer
- to which the view is attached.offset
- in bytes at which the view begins.length
- in bytes of the buffer included in the view.
-
wrap
public void wrap(java.nio.ByteBuffer buffer)
Attach a view to aByteBuffer
for providing direct access, theByteBuffer
can be heap based or direct. TheByteBuffer.order()
is not relevant for accessing the wrapped buffer.When using this method to wrap the view of the ByteBuffer the entire ByteBuffer gets wrapped between index 0 and capacity. If you want to just wrap the ByteBuffer between the position and the limit then you should use the
DirectBuffer.wrap(ByteBuffer, int, int)
method, eg:directBuffer.wrap(byteBuffer, byteBuffer.position(), byteBuffer.remaining());
- Specified by:
wrap
in interfaceDirectBuffer
- Parameters:
buffer
- to which the view is attached.
-
wrap
public void wrap(java.nio.ByteBuffer buffer, int offset, int length)
Attach a view to aByteBuffer
for providing direct access.The
ByteBuffer.order()
is not relevant for accessing the wrapped buffer.- Specified by:
wrap
in interfaceDirectBuffer
- Parameters:
buffer
- to which the view is attached.offset
- in bytes at which the view begins.length
- in bytes of the buffer included in the view.
-
wrap
public void wrap(DirectBuffer buffer)
Attach a view to an existingDirectBuffer
- Specified by:
wrap
in interfaceDirectBuffer
- Parameters:
buffer
- to which the view is attached.
-
wrap
public void wrap(DirectBuffer buffer, int offset, int length)
Attach a view to aDirectBuffer
for providing direct access.- Specified by:
wrap
in interfaceDirectBuffer
- Parameters:
buffer
- to which the view is attached.offset
- in bytes at which the view begins.length
- in bytes of the buffer included in the view.
-
wrap
public void wrap(long address, int length)
Attach a view to an off-heap memory region by address.- Specified by:
wrap
in interfaceDirectBuffer
- Parameters:
address
- where the memory begins off-heap.length
- of the buffer from the given address.
-
byteBuffer
public java.nio.ByteBuffer byteBuffer()
Get the underlyingByteBuffer
if one exists.NB: there may not be a one-to-one mapping between indices on this buffer and the underlying byte[], see
DirectBuffer.wrapAdjustment()
.- Specified by:
byteBuffer
in interfaceDirectBuffer
- Returns:
- the underlying
ByteBuffer
if one exists.
-
wrapAdjustment
public int wrapAdjustment()
Get the adjustment in indices between an index in this buffer and the wrapped object. The wrapped object might be aByteBuffer
or abyte[]
.You only need to use this adjustment if you plan to perform operations on the underlying byte array or byte buffer that rely on their indices.
- Specified by:
wrapAdjustment
in interfaceDirectBuffer
- Returns:
- the adjustment in indices between an index in this buffer and the wrapped object.
- See Also:
DirectBuffer.byteArray()
,DirectBuffer.byteBuffer()
-
isExpandable
public boolean isExpandable()
Is this buffer expandable to accommodate putting data into it beyond the current capacity?- Specified by:
isExpandable
in interfaceMutableDirectBuffer
- Returns:
- true is the underlying storage can expand otherwise false.
-
verifyAlignment
public void verifyAlignment()
Verify that the underlying buffer is correctly aligned to prevent word tearing, other ordering issues and the JVM crashes. In particular this method verifies that the starting offset of the underlying buffer is properly aligned. However, the actual atomic call must ensure that the index is properly aligned, i.e. it must be aligned to the size of the operand. For example a call to any of the following methodsAtomicBuffer.putIntOrdered(int, int)
,AtomicBuffer.putIntVolatile(int, int)
,AtomicBuffer.addIntOrdered(int, int)
,AtomicBuffer.getIntVolatile(int)
,AtomicBuffer.getAndAddInt(int, int)
orAtomicBuffer.getAndSetInt(int, int)
, must have the index aligned by four bytes (e.g.0, 4, 8, 12, 60 etc.
).Users are encouraged to call this method after constructing the
AtomicBuffer
instance in order to ensure that the underlying buffer supports atomic access tolong
values.Agrona provides an agent (
org.agrona.agent.BufferAlignmentAgent
) that checks the alignment of indexes for all operations at runtime. The agent throws an exception if the unaligned access is detected.Note: on some platforms unaligned atomic access can lead to the JVM crashes, e.g.:
# Java VM: OpenJDK 64-Bit Server VM (25.352-b08 mixed mode bsd-aarch64 compressed oops) # # siginfo: si_signo: 10 (SIGBUS), si_code: 1 (BUS_ADRALN)
- Specified by:
verifyAlignment
in interfaceAtomicBuffer
- See Also:
AtomicBuffer.ALIGNMENT
-
getLongVolatile
public long getLongVolatile(int index)
Get the value at a given index with volatile semantics.- Specified by:
getLongVolatile
in interfaceAtomicBuffer
- Parameters:
index
- in bytes from which to get.- Returns:
- the value for at a given index.
-
putLongVolatile
public void putLongVolatile(int index, long value)
Put a value to a given index with volatile semantics.- Specified by:
putLongVolatile
in interfaceAtomicBuffer
- Parameters:
index
- in bytes for where to put.value
- for at a given index.
-
putLongOrdered
public void putLongOrdered(int index, long value)
Put a value to a given index with ordered store semantics.- Specified by:
putLongOrdered
in interfaceAtomicBuffer
- Parameters:
index
- in bytes for where to put.value
- for at a given index.
-
addLongOrdered
public long addLongOrdered(int index, long increment)
Add a value to a given index with ordered store semantics. Use a negative increment to decrement.- Specified by:
addLongOrdered
in interfaceAtomicBuffer
- Parameters:
index
- in bytes for where to put.increment
- by which the value at the index will be adjusted.- Returns:
- the previous value at the index.
-
compareAndSetLong
public boolean compareAndSetLong(int index, long expectedValue, long updateValue)
Atomic compare and set of a long given an expected value.- Specified by:
compareAndSetLong
in interfaceAtomicBuffer
- Parameters:
index
- in bytes for where to put.expectedValue
- at to be compared.updateValue
- to be exchanged.- Returns:
- set successful or not.
-
getAndSetLong
public long getAndSetLong(int index, long value)
Atomically exchange a value at a location returning the previous contents.- Specified by:
getAndSetLong
in interfaceAtomicBuffer
- Parameters:
index
- in bytes for where to put.value
- for at a given index.- Returns:
- previous value at the index.
-
getAndAddLong
public long getAndAddLong(int index, long delta)
Atomically add a delta to a value at a location returning the previous contents. To decrement a negative delta can be provided.- Specified by:
getAndAddLong
in interfaceAtomicBuffer
- Parameters:
index
- in bytes for where to put.delta
- to be added to the value at the index.- Returns:
- previous value.
-
getIntVolatile
public int getIntVolatile(int index)
Get the value at a given index with volatile semantics.- Specified by:
getIntVolatile
in interfaceAtomicBuffer
- Parameters:
index
- in bytes from which to get.- Returns:
- the value for at a given index.
-
putIntVolatile
public void putIntVolatile(int index, int value)
Put a value to a given index with volatile semantics.- Specified by:
putIntVolatile
in interfaceAtomicBuffer
- Parameters:
index
- in bytes for where to put.value
- for at a given index.
-
putIntOrdered
public void putIntOrdered(int index, int value)
Put a value to a given index with ordered semantics.- Specified by:
putIntOrdered
in interfaceAtomicBuffer
- Parameters:
index
- in bytes for where to put.value
- for at a given index.
-
addIntOrdered
public int addIntOrdered(int index, int increment)
Add a value to a given index with ordered store semantics. Use a negative increment to decrement.- Specified by:
addIntOrdered
in interfaceAtomicBuffer
- Parameters:
index
- in bytes for where to put.increment
- by which the value at the index will be adjusted.- Returns:
- the previous value at the index.
-
compareAndSetInt
public boolean compareAndSetInt(int index, int expectedValue, int updateValue)
Atomic compare and set of an int given an expected value.- Specified by:
compareAndSetInt
in interfaceAtomicBuffer
- Parameters:
index
- in bytes for where to put.expectedValue
- at to be compared.updateValue
- to be exchanged.- Returns:
- successful or not.
-
getAndSetInt
public int getAndSetInt(int index, int value)
Atomically exchange a value at a location returning the previous contents.- Specified by:
getAndSetInt
in interfaceAtomicBuffer
- Parameters:
index
- in bytes for where to put.value
- for at a given index.- Returns:
- previous value.
-
getAndAddInt
public int getAndAddInt(int index, int delta)
Atomically add a delta to a value at a location returning the previous contents. To decrement a negative delta can be provided.- Specified by:
getAndAddInt
in interfaceAtomicBuffer
- Parameters:
index
- in bytes for where to put.delta
- to be added to the value at the index.- Returns:
- previous value.
-
getShortVolatile
public short getShortVolatile(int index)
Get the value at a given index with volatile semantics.- Specified by:
getShortVolatile
in interfaceAtomicBuffer
- Parameters:
index
- in bytes from which to get.- Returns:
- the value for at a given index.
-
putShortVolatile
public void putShortVolatile(int index, short value)
Put a value to a given index with volatile semantics.- Specified by:
putShortVolatile
in interfaceAtomicBuffer
- Parameters:
index
- in bytes for where to put.value
- for at a given index.
-
getByteVolatile
public byte getByteVolatile(int index)
Get the value at a given index with volatile semantics.- Specified by:
getByteVolatile
in interfaceAtomicBuffer
- Parameters:
index
- in bytes from which to get.- Returns:
- the value for at a given index.
-
putByteVolatile
public void putByteVolatile(int index, byte value)
Put a value to a given index with volatile semantics.- Specified by:
putByteVolatile
in interfaceAtomicBuffer
- Parameters:
index
- in bytes for where to put.value
- for at a given index.
-
getCharVolatile
public char getCharVolatile(int index)
Get the value at a given index with volatile semantics.- Specified by:
getCharVolatile
in interfaceAtomicBuffer
- Parameters:
index
- in bytes from which to get.- Returns:
- the value for at a given index.
-
putCharVolatile
public void putCharVolatile(int index, char value)
Put a value to a given index with volatile semantics.- Specified by:
putCharVolatile
in interfaceAtomicBuffer
- Parameters:
index
- in bytes for where to put.value
- for at a given index.
-
toString
public java.lang.String toString()
- Overrides:
toString
in classjava.lang.Object
-
ensureCapacity
protected final void ensureCapacity(int index, int length)
- Specified by:
ensureCapacity
in classAbstractMutableDirectBuffer
-
boundsCheckWrap
private static void boundsCheckWrap(int offset, int length, int capacity)
-
-