All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.datasketches.memory.BaseWritableBufferImpl Maven / Gradle / Ivy

There is a newer version: 5.0.0
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.datasketches.memory;

import static org.apache.datasketches.memory.UnsafeUtil.ARRAY_BOOLEAN_BASE_OFFSET;
import static org.apache.datasketches.memory.UnsafeUtil.ARRAY_BOOLEAN_INDEX_SCALE;
import static org.apache.datasketches.memory.UnsafeUtil.ARRAY_BYTE_BASE_OFFSET;
import static org.apache.datasketches.memory.UnsafeUtil.ARRAY_BYTE_INDEX_SCALE;
import static org.apache.datasketches.memory.UnsafeUtil.ARRAY_CHAR_INDEX_SCALE;
import static org.apache.datasketches.memory.UnsafeUtil.ARRAY_INT_INDEX_SCALE;
import static org.apache.datasketches.memory.UnsafeUtil.ARRAY_LONG_INDEX_SCALE;
import static org.apache.datasketches.memory.UnsafeUtil.ARRAY_SHORT_INDEX_SCALE;
import static org.apache.datasketches.memory.UnsafeUtil.checkBounds;
import static org.apache.datasketches.memory.UnsafeUtil.unsafe;

import java.nio.ByteOrder;

/*
 * Developer notes: The heavier methods, such as put/get arrays, duplicate, region, clear, fill,
 * compareTo, etc., use hard checks (check*() and incrementAndCheck*() methods), which execute at
 * runtime and throw exceptions if violated. The cost of the runtime checks are minor compared to
 * the rest of the work these methods are doing.
 *
 * 

The light weight methods, such as put/get primitives, use asserts (assert*() and * incrementAndAssert*() methods), which only execute when asserts are enabled and JIT will remove * them entirely from production runtime code. The offset versions of the light weight methods will * simplify to a single unsafe call, which is further simplified by JIT to an intrinsic that is * often a single CPU instruction. */ /** * Common base of native-ordered and non-native-ordered {@link WritableBuffer} implementations. * Contains methods which are agnostic to the byte order. */ abstract class BaseWritableBufferImpl extends WritableBuffer { final BaseWritableMemoryImpl originMemory; //Static variable for cases where byteBuf/array sizes are zero final static WritableBufferImpl ZERO_SIZE_BUFFER; static { final BaseWritableMemoryImpl mem = BaseWritableMemoryImpl.ZERO_SIZE_MEMORY; ZERO_SIZE_BUFFER = new HeapWritableBufferImpl(new byte[0], 0L, 0L, READONLY, mem); } //Pass-through ctor BaseWritableBufferImpl(final Object unsafeObj, final long nativeBaseOffset, final long regionOffset, final long capacityBytes, final BaseWritableMemoryImpl originMemory) { super(unsafeObj, nativeBaseOffset, regionOffset, capacityBytes); this.originMemory = originMemory; } //REGIONS @Override public Buffer region() { return writableRegionImpl(getPosition(), getEnd() - getPosition(), true, getTypeByteOrder()); } @Override public Buffer region(final long offsetBytes, final long capacityBytes, final ByteOrder byteOrder) { final Buffer buf = writableRegionImpl(offsetBytes, capacityBytes, true, byteOrder); buf.setAndCheckStartPositionEnd(0, 0, capacityBytes); return buf; } @Override public WritableBuffer writableRegion() { return writableRegionImpl(getPosition(), getEnd() - getPosition(), false, getTypeByteOrder()); } @Override public WritableBuffer writableRegion(final long offsetBytes, final long capacityBytes, final ByteOrder byteOrder) { final WritableBuffer wbuf = writableRegionImpl(offsetBytes, capacityBytes, false, byteOrder); wbuf.setAndCheckStartPositionEnd(0, 0, capacityBytes); return wbuf; } WritableBuffer writableRegionImpl(final long offsetBytes, final long capacityBytes, final boolean localReadOnly, final ByteOrder byteOrder) { if (capacityBytes == 0) { return ZERO_SIZE_BUFFER; } if (isReadOnly() && !localReadOnly) { throw new ReadOnlyException("Writable region of a read-only Buffer is not allowed."); } checkValidAndBounds(offsetBytes, capacityBytes); final boolean readOnly = isReadOnly() || localReadOnly; final WritableBuffer wbuf = toWritableRegion(offsetBytes, capacityBytes, readOnly, byteOrder); wbuf.setStartPositionEnd(0, 0, capacityBytes); return wbuf; } abstract BaseWritableBufferImpl toWritableRegion( long offsetBytes, long capcityBytes, boolean readOnly, ByteOrder byteOrder); //DUPLICATES @Override public Buffer duplicate() { return writableDuplicateImpl(true, getTypeByteOrder()); } @Override public Buffer duplicate(final ByteOrder byteOrder) { return writableDuplicateImpl(true, byteOrder); } @Override public WritableBuffer writableDuplicate() { return writableDuplicateImpl(false, getTypeByteOrder()); } @Override public WritableBuffer writableDuplicate(final ByteOrder byteOrder) { return writableDuplicateImpl(false, byteOrder); } WritableBuffer writableDuplicateImpl(final boolean localReadOnly, final ByteOrder byteOrder) { if (isReadOnly() && !localReadOnly) { throw new ReadOnlyException("Writable duplicate of a read-only Buffer is not allowed."); } final boolean readOnly = isReadOnly() || localReadOnly; final WritableBuffer wbuf = toDuplicate(readOnly, byteOrder); wbuf.setStartPositionEnd(getStart(), getPosition(), getEnd()); return wbuf; } abstract BaseWritableBufferImpl toDuplicate(boolean readOnly, ByteOrder byteOrder); //MEMORY @Override public Memory asMemory() { return originMemory; } @Override public WritableMemory asWritableMemory() { if (isReadOnly()) { throw new ReadOnlyException("Converting a read-only Buffer to a writable Memory is not allowed."); } return originMemory; } //PRIMITIVE getX() and getArray() @Override public final boolean getBoolean() { final long pos = getPosition(); incrementAndAssertPositionForRead(pos, ARRAY_BOOLEAN_INDEX_SCALE); return unsafe.getBoolean(getUnsafeObject(), getCumulativeOffset(pos)); } @Override public final boolean getBoolean(final long offsetBytes) { assertValidAndBoundsForRead(offsetBytes, ARRAY_BOOLEAN_INDEX_SCALE); return unsafe.getBoolean(getUnsafeObject(), getCumulativeOffset(offsetBytes)); } @Override public final void getBooleanArray(final boolean[] dstArray, final int dstOffsetBooleans, final int lengthBooleans) { final long pos = getPosition(); final long copyBytes = lengthBooleans; incrementAndCheckPositionForRead(pos, copyBytes); checkBounds(dstOffsetBooleans, lengthBooleans, dstArray.length); CompareAndCopy.copyMemoryCheckingDifferentObject( getUnsafeObject(), getCumulativeOffset(pos), dstArray, ARRAY_BOOLEAN_BASE_OFFSET + dstOffsetBooleans, copyBytes); } @Override public final byte getByte() { final long pos = getPosition(); incrementAndAssertPositionForRead(pos, ARRAY_BYTE_INDEX_SCALE); return unsafe.getByte(getUnsafeObject(), getCumulativeOffset(pos)); } @Override public final byte getByte(final long offsetBytes) { assertValidAndBoundsForRead(offsetBytes, ARRAY_BYTE_INDEX_SCALE); return unsafe.getByte(getUnsafeObject(), getCumulativeOffset(offsetBytes)); } @Override public final void getByteArray(final byte[] dstArray, final int dstOffsetBytes, final int lengthBytes) { final long pos = getPosition(); final long copyBytes = lengthBytes; incrementAndCheckPositionForRead(pos, copyBytes); checkBounds(dstOffsetBytes, lengthBytes, dstArray.length); CompareAndCopy.copyMemoryCheckingDifferentObject( getUnsafeObject(), getCumulativeOffset(pos), dstArray, ARRAY_BYTE_BASE_OFFSET + dstOffsetBytes, copyBytes); } //PRIMITIVE getX() Native Endian (used by both endians) final char getNativeOrderedChar() { final long pos = getPosition(); incrementAndAssertPositionForRead(pos, ARRAY_CHAR_INDEX_SCALE); return unsafe.getChar(getUnsafeObject(), getCumulativeOffset(pos)); } final char getNativeOrderedChar(final long offsetBytes) { assertValidAndBoundsForRead(offsetBytes, ARRAY_CHAR_INDEX_SCALE); return unsafe.getChar(getUnsafeObject(), getCumulativeOffset(offsetBytes)); } final int getNativeOrderedInt() { final long pos = getPosition(); incrementAndAssertPositionForRead(pos, ARRAY_INT_INDEX_SCALE); return unsafe.getInt(getUnsafeObject(), getCumulativeOffset(pos)); } final int getNativeOrderedInt(final long offsetBytes) { assertValidAndBoundsForRead(offsetBytes, ARRAY_INT_INDEX_SCALE); return unsafe.getInt(getUnsafeObject(), getCumulativeOffset(offsetBytes)); } final long getNativeOrderedLong() { final long pos = getPosition(); incrementAndAssertPositionForRead(pos, ARRAY_LONG_INDEX_SCALE); return unsafe.getLong(getUnsafeObject(), getCumulativeOffset(pos)); } final long getNativeOrderedLong(final long offsetBytes) { assertValidAndBoundsForRead(offsetBytes, ARRAY_LONG_INDEX_SCALE); return unsafe.getLong(getUnsafeObject(), getCumulativeOffset(offsetBytes)); } final short getNativeOrderedShort() { final long pos = getPosition(); incrementAndAssertPositionForRead(pos, ARRAY_SHORT_INDEX_SCALE); return unsafe.getShort(getUnsafeObject(), getCumulativeOffset(pos)); } final short getNativeOrderedShort(final long offsetBytes) { assertValidAndBoundsForRead(offsetBytes, ARRAY_SHORT_INDEX_SCALE); return unsafe.getShort(getUnsafeObject(), getCumulativeOffset(offsetBytes)); } //OTHER PRIMITIVE READ METHODS: copyTo, compareTo @Override public final int compareTo(final long thisOffsetBytes, final long thisLengthBytes, final Buffer thatBuf, final long thatOffsetBytes, final long thatLengthBytes) { return CompareAndCopy.compare(this, thisOffsetBytes, thisLengthBytes, thatBuf, thatOffsetBytes, thatLengthBytes); } /* * Develper notes: There is no copyTo for Buffers because of the ambiguity of what to do with * the positional values. Switch to Memory view to do copyTo. */ //PRIMITIVE putX() and putXArray() @Override public final void putBoolean(final boolean value) { final long pos = getPosition(); incrementAndAssertPositionForWrite(pos, ARRAY_BOOLEAN_INDEX_SCALE); unsafe.putBoolean(getUnsafeObject(), getCumulativeOffset(pos), value); } @Override public final void putBoolean(final long offsetBytes, final boolean value) { assertValidAndBoundsForWrite(offsetBytes, ARRAY_BOOLEAN_INDEX_SCALE); unsafe.putBoolean(getUnsafeObject(), getCumulativeOffset(offsetBytes), value); } @Override public final void putBooleanArray(final boolean[] srcArray, final int srcOffsetBooleans, final int lengthBooleans) { final long pos = getPosition(); final long copyBytes = lengthBooleans; incrementAndCheckPositionForWrite(pos, copyBytes); checkBounds(srcOffsetBooleans, lengthBooleans, srcArray.length); CompareAndCopy.copyMemoryCheckingDifferentObject( srcArray, ARRAY_BOOLEAN_BASE_OFFSET + srcOffsetBooleans, getUnsafeObject(), getCumulativeOffset(pos), copyBytes); } @Override public final void putByte(final byte value) { final long pos = getPosition(); incrementAndAssertPositionForWrite(pos, ARRAY_BYTE_INDEX_SCALE); unsafe.putByte(getUnsafeObject(), getCumulativeOffset(pos), value); } @Override public final void putByte(final long offsetBytes, final byte value) { assertValidAndBoundsForWrite(offsetBytes, ARRAY_BYTE_INDEX_SCALE); unsafe.putByte(getUnsafeObject(), getCumulativeOffset(offsetBytes), value); } @Override public final void putByteArray(final byte[] srcArray, final int srcOffsetBytes, final int lengthBytes) { final long pos = getPosition(); final long copyBytes = lengthBytes; incrementAndCheckPositionForWrite(pos, copyBytes); checkBounds(srcOffsetBytes, lengthBytes, srcArray.length); CompareAndCopy.copyMemoryCheckingDifferentObject( srcArray, ARRAY_BYTE_BASE_OFFSET + srcOffsetBytes, getUnsafeObject(), getCumulativeOffset(pos), copyBytes); } //PRIMITIVE putX() Native Endian (used by both endians) final void putNativeOrderedChar(final char value) { final long pos = getPosition(); incrementAndAssertPositionForWrite(pos, ARRAY_CHAR_INDEX_SCALE); unsafe.putChar(getUnsafeObject(), getCumulativeOffset(pos), value); } final void putNativeOrderedChar(final long offsetBytes, final char value) { assertValidAndBoundsForWrite(offsetBytes, ARRAY_CHAR_INDEX_SCALE); unsafe.putChar(getUnsafeObject(), getCumulativeOffset(offsetBytes), value); } final void putNativeOrderedInt(final int value) { final long pos = getPosition(); incrementAndAssertPositionForWrite(pos, ARRAY_INT_INDEX_SCALE); unsafe.putInt(getUnsafeObject(), getCumulativeOffset(pos), value); } final void putNativeOrderedInt(final long offsetBytes, final int value) { assertValidAndBoundsForWrite(offsetBytes, ARRAY_INT_INDEX_SCALE); unsafe.putInt(getUnsafeObject(), getCumulativeOffset(offsetBytes), value); } final void putNativeOrderedLong(final long value) { final long pos = getPosition(); incrementAndAssertPositionForWrite(pos, ARRAY_LONG_INDEX_SCALE); unsafe.putLong(getUnsafeObject(), getCumulativeOffset(pos), value); } final void putNativeOrderedLong(final long offsetBytes, final long value) { assertValidAndBoundsForWrite(offsetBytes, ARRAY_LONG_INDEX_SCALE); unsafe.putLong(getUnsafeObject(), getCumulativeOffset(offsetBytes), value); } final void putNativeOrderedShort(final short value) { final long pos = getPosition(); incrementAndAssertPositionForWrite(pos, ARRAY_SHORT_INDEX_SCALE); unsafe.putShort(getUnsafeObject(), getCumulativeOffset(pos), value); } final void putNativeOrderedShort(final long offsetBytes, final short value) { assertValidAndBoundsForWrite(offsetBytes, ARRAY_SHORT_INDEX_SCALE); unsafe.putShort(getUnsafeObject(), getCumulativeOffset(offsetBytes), value); } //OTHER @Override public final Object getArray() { assertValid(); return getUnsafeObject(); } @Override public final void clear() { fill((byte)0); } @Override public final void fill(final byte value) { checkValidForWrite(); long pos = getPosition(); long len = getEnd() - pos; checkInvariants(getStart(), pos + len, getEnd(), getCapacity()); while (len > 0) { final long chunk = Math.min(len, CompareAndCopy.UNSAFE_COPY_THRESHOLD_BYTES); unsafe.setMemory(getUnsafeObject(), getCumulativeOffset(pos), chunk, value); pos += chunk; len -= chunk; } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy