Class 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 various ByteBuffer implementations, or an off Java heap memory address.

    ByteOrder of a wrapped buffer is not applied to the UnsafeBuffer. UnsafeBuffers are effectively stateless and can be used concurrently, the wrapping methods are an exception. To control ByteOrder use the appropriate method with the ByteOrder 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.

    • Constructor Detail

      • UnsafeBuffer

        public UnsafeBuffer()
        Empty constructor for a reusable wrapper buffer.
      • UnsafeBuffer

        public UnsafeBuffer​(byte[] buffer)
        Attach a view to a byte[] 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 a byte[] 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 a ByteBuffer for providing direct access, the ByteBuffer 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 a ByteBuffer for providing direct access, the ByteBuffer 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 existing DirectBuffer
        Parameters:
        buffer - to which the view is attached.
      • UnsafeBuffer

        public UnsafeBuffer​(DirectBuffer buffer,
                            int offset,
                            int length)
        Attach a view to an existing DirectBuffer
        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-heap
        length - of the buffer from the given address
    • Method Detail

      • wrap

        public void wrap​(byte[] buffer)
        Attach a view to a byte[] for providing direct access.
        Specified by:
        wrap in interface DirectBuffer
        Parameters:
        buffer - to which the view is attached.
      • wrap

        public void wrap​(byte[] buffer,
                         int offset,
                         int length)
        Attach a view to a byte[] for providing direct access.
        Specified by:
        wrap in interface DirectBuffer
        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 a ByteBuffer for providing direct access, the ByteBuffer can be heap based or direct. The ByteBuffer.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 interface DirectBuffer
        Parameters:
        buffer - to which the view is attached.
      • wrap

        public void wrap​(java.nio.ByteBuffer buffer,
                         int offset,
                         int length)
        Attach a view to a ByteBuffer for providing direct access.

        The ByteBuffer.order() is not relevant for accessing the wrapped buffer.

        Specified by:
        wrap in interface DirectBuffer
        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,
                         int offset,
                         int length)
        Attach a view to a DirectBuffer for providing direct access.
        Specified by:
        wrap in interface DirectBuffer
        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 interface DirectBuffer
        Parameters:
        address - where the memory begins off-heap.
        length - of the buffer from the given address.
      • byteBuffer

        public java.nio.ByteBuffer byteBuffer()
        Get the underlying ByteBuffer 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 interface DirectBuffer
        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 a ByteBuffer or a byte[].

        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 interface DirectBuffer
        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 interface MutableDirectBuffer
        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 methods AtomicBuffer.putIntOrdered(int, int), AtomicBuffer.putIntVolatile(int, int), AtomicBuffer.addIntOrdered(int, int), AtomicBuffer.getIntVolatile(int), AtomicBuffer.getAndAddInt(int, int) or AtomicBuffer.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 to long 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 interface AtomicBuffer
        See Also:
        AtomicBuffer.ALIGNMENT
      • getLongVolatile

        public long getLongVolatile​(int index)
        Get the value at a given index with volatile semantics.
        Specified by:
        getLongVolatile in interface AtomicBuffer
        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 interface AtomicBuffer
        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 interface AtomicBuffer
        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 interface AtomicBuffer
        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 interface AtomicBuffer
        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 interface AtomicBuffer
        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 interface AtomicBuffer
        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 interface AtomicBuffer
        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 interface AtomicBuffer
        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 interface AtomicBuffer
        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 interface AtomicBuffer
        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 interface AtomicBuffer
        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 interface AtomicBuffer
        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 interface AtomicBuffer
        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 interface AtomicBuffer
        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 interface AtomicBuffer
        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 interface AtomicBuffer
        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 interface AtomicBuffer
        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 interface AtomicBuffer
        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 interface AtomicBuffer
        Parameters:
        index - in bytes for where to put.
        value - for at a given index.
      • toString

        public java.lang.String toString()
        Overrides:
        toString in class java.lang.Object
      • boundsCheckWrap

        private static void boundsCheckWrap​(int offset,
                                            int length,
                                            int capacity)