HCOLL-284 better assert-independent bounds checking

This commit is contained in:
leventov
2014-12-31 06:46:22 +07:00
parent c9224cd690
commit 0d14d7fc78
4 changed files with 63 additions and 48 deletions
@@ -20,7 +20,6 @@ package net.openhft.chronicle.hash.serialization.internal;
import net.openhft.chronicle.hash.serialization.BytesWriter;
import net.openhft.lang.MemoryUnit;
import net.openhft.lang.io.Bytes;
import net.openhft.lang.io.serialization.BytesMarshaller;
import net.openhft.lang.threadlocal.ThreadLocalCopies;
@@ -49,28 +48,6 @@ public abstract class CopyingMetaBytesInterop<E, W> extends BasicCopyingMetaByte
super(buffer);
}
void init(W writer, E e, boolean mutable, long maxSize) {
if (mutable || writer != this.writer || e != cur) {
this.writer = writer;
cur = e;
while (true) {
try {
Bytes buffer = this.buffer.obtain(maxSize);
innerWrite(writer, buffer, e);
buffer.flip();
size = buffer.remaining();
hash = 0L;
return;
} catch (Exception ex) {
checkMaxSizeStillReasonable(maxSize, ex);
maxSize *= 2L;
}
}
}
}
abstract void innerWrite(W writer, Bytes bytes, E e);
DirectBytesBuffer buffer() {
return buffer;
}
@@ -88,7 +65,7 @@ public abstract class CopyingMetaBytesInterop<E, W> extends BasicCopyingMetaByte
public static <E, M extends BytesMarshaller<E>>
MetaProvider<E, M, CopyingMetaBytesInterop<E, M>> providerForBytesMarshaller(boolean mutable,
long maxSize) {
return new BytesMarshallerCopyingMetaBytesInteropProvider<E, M>(mutable, maxSize);
return new BytesMarshallerCopyingMetaBytesInteropProvider<>(mutable, maxSize);
}
private static class BytesMarshallerCopyingMetaBytesInteropProvider<E,
@@ -115,30 +92,25 @@ public abstract class CopyingMetaBytesInterop<E, W> extends BasicCopyingMetaByte
}
public static <E, W extends BytesWriter<E>>
MetaProvider<E, W, CopyingMetaBytesInterop<E, W>> providerForBytesWriter(boolean mutable,
long maxSize) {
return new BytesWriterCopyingMetaBytesInteropProvider<E, W>(mutable, maxSize);
MetaProvider<E, W, CopyingMetaBytesInterop<E, W>> providerForBytesWriter(boolean mutable) {
return new BytesWriterCopyingMetaBytesInteropProvider<>(mutable);
}
private static class BytesWriterCopyingMetaBytesInteropProvider<E, W extends BytesWriter<E>>
extends BasicCopyingMetaBytesInteropProvider<E, W, CopyingMetaBytesInterop<E, W>> {
private static final long serialVersionUID = 0L;
private final boolean mutable;
private final long maxSize;
public BytesWriterCopyingMetaBytesInteropProvider(boolean mutable, long maxSize) {
public BytesWriterCopyingMetaBytesInteropProvider(boolean mutable) {
this.mutable = mutable;
this.maxSize = maxSize;
}
@Override
public CopyingMetaBytesInterop<E, W> get(
ThreadLocalCopies copies,
public CopyingMetaBytesInterop<E, W> get(ThreadLocalCopies copies,
CopyingMetaBytesInterop<E, W> originalMetaWriter, W writer, E e) {
DirectBytesBuffer.ForBytesWriter forBytesWriter =
provider.get(copies, originalMetaWriter.buffer()).forBytesWriter;
forBytesWriter.buffer.obtain(writer.size(e));
forBytesWriter.init(writer, e, mutable, maxSize);
forBytesWriter.init(writer, e, mutable);
return forBytesWriter;
}
}
@@ -34,9 +34,10 @@ public abstract class DataValueMetaBytesInterop<E>
}
void init(BytesWriter<E> writer, E e, long size) {
Bytes buffer = this.buffer.obtain(size);
Bytes buffer = this.buffer.obtain(size, false);
writer.write(buffer, e);
buffer.flip();
assert buffer.remaining() == size;
this.size = size;
hash = 0L;
}
@@ -17,6 +17,7 @@
package net.openhft.chronicle.hash.serialization.internal;
import net.openhft.chronicle.hash.serialization.BytesWriter;
import net.openhft.lang.io.BoundsCheckingNativeBytes;
import net.openhft.lang.io.Bytes;
import net.openhft.lang.io.DirectBytes;
import net.openhft.lang.io.DirectStore;
@@ -33,6 +34,7 @@ class DirectBytesBuffer
private static final long serialVersionUID = 0L;
private final Serializable identity;
transient DirectBytes buffer;
transient BoundsCheckingNativeBytes checkingBuffer;
transient ForBytesMarshaller forBytesMarshaller;
transient ForBytesWriter forBytesWriter;
@@ -54,19 +56,33 @@ class DirectBytesBuffer
forDataValueWriter = new ForDataValueWriter();
}
Bytes obtain(long maxSize) {
Bytes obtain(long maxSize, boolean boundsChecking) {
DirectBytes buf;
if ((buf = buffer) != null) {
if (maxSize <= buf.capacity()) {
return buf.clear();
if (!boundsChecking)
return buf.clear();
Bytes checkingBuf;
if ((checkingBuf = checkingBuffer) != null) {
return checkingBuf.clear();
} else {
return (checkingBuffer = new BoundsCheckingNativeBytes(buf)).clear();
}
} else {
DirectStore store = (DirectStore) buf.store();
store.resize(maxSize, false);
return buffer = store.bytes();
store.resize(maxSize, true);
buf = buffer = store.bytes();
if (!boundsChecking)
return buf;
return (checkingBuffer = new BoundsCheckingNativeBytes(buf));
}
} else {
buffer = new DirectStore(JDKObjectSerializer.INSTANCE, maxSize, false).bytes();
return buffer;
buf = buffer = new DirectStore(JDKObjectSerializer.INSTANCE,
// don't allocate 0 bytes
Math.max(1, maxSize), true).bytes();
if (!boundsChecking)
return buf;
return (checkingBuffer = new BoundsCheckingNativeBytes(buf));
}
}
@@ -88,9 +104,26 @@ class DirectBytesBuffer
super(DirectBytesBuffer.this);
}
@Override
void innerWrite(M writer, Bytes bytes, E e) {
writer.write(bytes, e);
void init(M writer, E e, boolean mutable, long maxSize) {
if (mutable || writer != this.writer || e != cur) {
this.writer = writer;
cur = e;
while (true) {
try {
Bytes buffer = this.buffer.obtain(maxSize, true);
writer.write(buffer, e);
buffer.flip();
long size = this.size = buffer.remaining();
this.buffer.buffer.position(0L);
this.buffer.buffer.limit(size);
hash = 0L;
return;
} catch (Exception ex) {
checkMaxSizeStillReasonable(maxSize, ex);
maxSize *= 2L;
}
}
}
}
}
@@ -102,9 +135,18 @@ class DirectBytesBuffer
super(DirectBytesBuffer.this);
}
@Override
void innerWrite(W writer, Bytes bytes, E e) {
writer.write(bytes, e);
void init(W writer, E e, boolean mutable) {
if (mutable || writer != this.writer || e != cur) {
this.writer = writer;
cur = e;
long size = writer.size(e);
Bytes buffer = this.buffer.obtain(size, false);
writer.write(buffer, e);
buffer.flip();
this.size = size;
assert size == buffer.remaining();
hash = 0L;
}
}
}
@@ -240,7 +240,7 @@ final class SerializationBuilder<E> implements Cloneable, Serializable {
} else if (copyingInterop == CopyingInterop.FROM_WRITER) {
this.maxSize = maxSize;
metaInteropProvider(CopyingMetaBytesInterop
.<E, BytesWriter<E>>providerForBytesWriter(instancesAreMutable, maxSize));
.<E, BytesWriter<E>>providerForBytesWriter(instancesAreMutable));
}
return this;
}