From 35bde75d5239dee4ce976a22f31bb9044965d0b0 Mon Sep 17 00:00:00 2001 From: Chris Vest Date: Mon, 24 Aug 2020 17:13:04 +0200 Subject: [PATCH] Introduce a Buf interface The intent is that this will hide the BBuf implementation in the long run. For the time being, it highlights an issue with the Rc family of types and their generics, and specifically how they are complicated to compose with other interfaces. --- .../java/io/netty/buffer/b2/Allocator.java | 15 ++++---- .../main/java/io/netty/buffer/b2/BBuf.java | 34 ++++++++++++++--- .../src/main/java/io/netty/buffer/b2/Buf.java | 37 +++++++++++++++++++ .../io/netty/buffer/BBufAccessBenchmark.java | 2 +- 4 files changed, 73 insertions(+), 15 deletions(-) create mode 100644 buffer/src/main/java/io/netty/buffer/b2/Buf.java diff --git a/buffer/src/main/java/io/netty/buffer/b2/Allocator.java b/buffer/src/main/java/io/netty/buffer/b2/Allocator.java index 44b3fc3..ca84ab1 100644 --- a/buffer/src/main/java/io/netty/buffer/b2/Allocator.java +++ b/buffer/src/main/java/io/netty/buffer/b2/Allocator.java @@ -5,9 +5,8 @@ import jdk.incubator.foreign.MemorySegment; import static io.netty.buffer.b2.BBuf.*; /** - * Interface for {@link BBuf} allocators. + * Interface for {@link Buf} allocators. */ -@SuppressWarnings("InterfaceMayBeAnnotatedFunctional") public interface Allocator extends AutoCloseable { static void checkSize(long size) { if (size < 1) { @@ -22,13 +21,13 @@ public interface Allocator extends AutoCloseable { } /** - * Allocate a {@link BBuf} of the given size in bytes. This method may throw an {@link OutOfMemoryError} if there is - * not enough free memory available to allocate a {@link BBuf} of the requested size. + * Allocate a {@link Buf} of the given size in bytes. This method may throw an {@link OutOfMemoryError} if there is + * not enough free memory available to allocate a {@link Buf} of the requested size. * - * @param size The size of {@link BBuf} to allocate. - * @return The newly allocated {@link BBuf}. + * @param size The size of {@link Buf} to allocate. + * @return The newly allocated {@link Buf}. */ - BBuf allocate(long size); + > T allocate(long size); /** * Close this allocator, freeing all of its internal resources. It is not specified if the allocator can still be @@ -52,7 +51,7 @@ public interface Allocator extends AutoCloseable { static Allocator direct() { return new Allocator() { @Override - public BBuf allocate(long size) { + public Buf allocate(long size) { checkSize(size); var segment = MemorySegment.allocateNative(size); Statics.MEM_USAGE_NATIVE.add(size); diff --git a/buffer/src/main/java/io/netty/buffer/b2/BBuf.java b/buffer/src/main/java/io/netty/buffer/b2/BBuf.java index a2902e1..3b492bb 100644 --- a/buffer/src/main/java/io/netty/buffer/b2/BBuf.java +++ b/buffer/src/main/java/io/netty/buffer/b2/BBuf.java @@ -7,7 +7,7 @@ import jdk.incubator.foreign.MemorySegment; import static io.netty.buffer.b2.Statics.*; -public class BBuf extends RcSupport { +public class BBuf extends RcSupport implements Buf { static final Drop NO_DROP = buf -> {}; static final Drop SEGMENT_CLOSE = buf -> buf.segment.close(); static final Drop SEGMENT_CLOSE_NATIVE = buf -> { @@ -23,16 +23,27 @@ public class BBuf extends RcSupport { this.segment = segment; } + @Override + public int readerIndex() { + return read; + } + + @Override public BBuf readerIndex(int index) { - if (index < 0 || segment.byteSize() <= index) { - throw new IndexOutOfBoundsException( - "Index " + index + " is out of bounds: [0 to " + segment.byteSize() + "]."); - } + checkIndexBounds(index); read = index; return this; } - public BBuf touch() { + @Override + public int writerIndex() { + return write; + } + + @Override + public BBuf writerIndex(int index) { + checkIndexBounds(index); + write = index; return this; } @@ -100,4 +111,15 @@ public class BBuf extends RcSupport { } }; } + + private void checkIndexBounds(int index) { + if (index < 0 || segment.byteSize() <= index) { + throw indexOutOfBounds(index); + } + } + + private IndexOutOfBoundsException indexOutOfBounds(int index) { + return new IndexOutOfBoundsException( + "Index " + index + " is out of bounds: [0 to " + segment.byteSize() + "]."); + } } diff --git a/buffer/src/main/java/io/netty/buffer/b2/Buf.java b/buffer/src/main/java/io/netty/buffer/b2/Buf.java new file mode 100644 index 0000000..6983483 --- /dev/null +++ b/buffer/src/main/java/io/netty/buffer/b2/Buf.java @@ -0,0 +1,37 @@ +package io.netty.buffer.b2; + +/** + * A reference counted buffer API with separate reader and writer indexes. + * @param The concrete runtime buffer type. + */ +public interface Buf> extends Rc { + /** + * Get the current reader index. The next read will happen from this byte index into the buffer. + * + * @return The current reader index. + */ + int readerIndex(); + + /** + * Set the reader index. Make the next read happen from the given index. + * + * @param index The reader index to set. + * @return This Buf. + */ + T readerIndex(int index); + + /** + * Get the current writer index. The next write will happen at this byte index into the byffer. + * + * @return The current writer index. + */ + int writerIndex(); + + /** + * Set the writer index. Make the next write happen at the given index. + * + * @param index The writer index to set. + * @return This Buf. + */ + T writerIndex(int index); +} diff --git a/microbench/src/main/java/io/netty/buffer/BBufAccessBenchmark.java b/microbench/src/main/java/io/netty/buffer/BBufAccessBenchmark.java index 47da07f..ccf74c8 100644 --- a/microbench/src/main/java/io/netty/buffer/BBufAccessBenchmark.java +++ b/microbench/src/main/java/io/netty/buffer/BBufAccessBenchmark.java @@ -102,7 +102,7 @@ public class BBufAccessBenchmark extends AbstractMicrobenchmark { @Benchmark public int readBatch() { - buffer.readerIndex(0).touch(); + buffer.readerIndex(0); int result = 0; // WARNING! // Please do not replace this sum loop with a BlackHole::consume loop: