First draft of splitting the repo into multiple modules and allowing builds with Java 11
This commit is contained in:
parent
99cddf7749
commit
1143223407
@ -29,8 +29,12 @@ RUN git clone --depth 1 -b master https://github.com/netty/netty.git netty \
|
||||
&& rm -fr netty
|
||||
|
||||
# Prepare our own build
|
||||
RUN mkdir buffer-api && mkdir buffer-memseg && mkdir buffer-tests
|
||||
COPY pom.xml pom.xml
|
||||
RUN mvn dependency:go-offline surefire:test checkstyle:check -ntp
|
||||
COPY buffer-api/pom.xml buffer-api/pom.xml
|
||||
COPY buffer-memseg/pom.xml buffer-memseg/pom.xml
|
||||
COPY buffer-tests/pom.xml buffer-tests/pom.xml
|
||||
RUN mvn install dependency:go-offline surefire:test checkstyle:check -ntp
|
||||
|
||||
# Copy over the project code and run our build
|
||||
COPY . .
|
||||
|
43
buffer-api/pom.xml
Normal file
43
buffer-api/pom.xml
Normal file
@ -0,0 +1,43 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 2021 The Netty Project
|
||||
~
|
||||
~ The Netty Project 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:
|
||||
~
|
||||
~ https://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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>io.netty.incubator</groupId>
|
||||
<artifactId>netty-incubator-buffer-parent</artifactId>
|
||||
<version>0.0.1.Final-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>netty-incubator-buffer-api</artifactId>
|
||||
<version>0.0.1.Final-SNAPSHOT</version>
|
||||
<name>Netty/Incubator/Buffer</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-common</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-buffer</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@ -15,10 +15,11 @@
|
||||
*/
|
||||
package io.netty.buffer.api;
|
||||
|
||||
import io.netty.buffer.api.internal.Statics;
|
||||
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.util.Objects;
|
||||
|
||||
import static io.netty.buffer.api.internal.Statics.findVarHandle;
|
||||
import static java.lang.invoke.MethodHandles.lookup;
|
||||
|
||||
/**
|
||||
@ -36,7 +37,7 @@ import static java.lang.invoke.MethodHandles.lookup;
|
||||
* @param <T> The concrete {@link BufferHolder} type.
|
||||
*/
|
||||
public abstract class BufferHolder<T extends BufferHolder<T>> implements Rc<T> {
|
||||
private static final VarHandle BUF = findVarHandle(lookup(), BufferHolder.class, "buf", Buffer.class);
|
||||
private static final VarHandle BUF = Statics.findVarHandle(lookup(), BufferHolder.class, "buf", Buffer.class);
|
||||
private Buffer buf;
|
||||
|
||||
/**
|
@ -15,7 +15,6 @@
|
||||
*/
|
||||
package io.netty.buffer.api;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.util.ArrayDeque;
|
||||
import java.util.Set;
|
||||
import java.util.function.Function;
|
||||
@ -176,7 +175,6 @@ abstract class LifecycleTracer {
|
||||
}
|
||||
|
||||
private static final class Traceback extends Throwable {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 941453986194634605L;
|
||||
|
||||
Traceback(String message) {
|
@ -15,7 +15,7 @@
|
||||
*/
|
||||
package io.netty.buffer.api;
|
||||
|
||||
import io.netty.buffer.api.memseg.SegmentMemoryManagers;
|
||||
import io.netty.buffer.api.bytebuffer.ByteBufferMemoryManagers;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.IdentityHashMap;
|
||||
@ -24,7 +24,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
final class MemoryManagersOverride {
|
||||
private static final MemoryManagers DEFAULT = new SegmentMemoryManagers();
|
||||
private static final MemoryManagers DEFAULT = new ByteBufferMemoryManagers();
|
||||
private static final AtomicInteger OVERRIDES_AVAILABLE = new AtomicInteger();
|
||||
private static final Map<Thread, MemoryManagers> OVERRIDES = Collections.synchronizedMap(new IdentityHashMap<>());
|
||||
|
@ -15,13 +15,14 @@
|
||||
*/
|
||||
package io.netty.buffer.api;
|
||||
|
||||
import io.netty.buffer.api.internal.Statics;
|
||||
|
||||
import java.lang.invoke.VarHandle;
|
||||
|
||||
import static io.netty.buffer.api.internal.Statics.findVarHandle;
|
||||
import static java.lang.invoke.MethodHandles.lookup;
|
||||
|
||||
class TransferSend<I extends Rc<I>, T extends Rc<I>> implements Send<I> {
|
||||
private static final VarHandle RECEIVED = findVarHandle(lookup(), TransferSend.class, "received", boolean.class);
|
||||
private static final VarHandle RECEIVED = Statics.findVarHandle(lookup(), TransferSend.class, "received", boolean.class);
|
||||
private final Owned<T> outgoing;
|
||||
private final Drop<T> drop;
|
||||
private final Class<?> concreteType;
|
@ -22,8 +22,9 @@ import io.netty.buffer.ByteBufUtil;
|
||||
import io.netty.buffer.DuplicatedByteBuf;
|
||||
import io.netty.buffer.SlicedByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import io.netty.buffer.api.Buffer;
|
||||
import io.netty.buffer.api.BufferAllocator;
|
||||
import io.netty.buffer.api.internal.Statics;
|
||||
import io.netty.buffer.api.Buffer;
|
||||
import io.netty.buffer.api.RcSupport;
|
||||
import io.netty.util.ByteProcessor;
|
||||
import io.netty.util.IllegalReferenceCountException;
|
||||
@ -1514,7 +1515,7 @@ public final class ByteBufAdaptor extends ByteBuf {
|
||||
});
|
||||
ByteBuffer buffer = bufRef.get();
|
||||
if (index != readerIndex() || length != readableBytes()) {
|
||||
buffer = buffer.slice(index - readerIndex(), length);
|
||||
buffer = Statics.bbslice(buffer, index - readerIndex(), length);
|
||||
}
|
||||
return buffer;
|
||||
} else if (writerIndex() <= index && length <= writableBytes()) {
|
||||
@ -1530,7 +1531,7 @@ public final class ByteBufAdaptor extends ByteBuf {
|
||||
});
|
||||
ByteBuffer buffer = bufRef.get();
|
||||
if (index != writerIndex() || length != writableBytes()) {
|
||||
buffer = buffer.slice(index - writerIndex(), length);
|
||||
buffer = Statics.bbslice(buffer, index - writerIndex(), length);
|
||||
}
|
||||
return buffer;
|
||||
} else {
|
@ -25,6 +25,7 @@ import java.lang.ref.Cleaner;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import static io.netty.buffer.api.internal.Statics.bbslice;
|
||||
import static io.netty.buffer.api.internal.Statics.convert;
|
||||
|
||||
public class ByteBufferMemoryManager implements MemoryManager {
|
||||
@ -84,6 +85,6 @@ public class ByteBufferMemoryManager implements MemoryManager {
|
||||
@Override
|
||||
public Object sliceMemory(Object memory, int offset, int length) {
|
||||
var buffer = (ByteBuffer) memory;
|
||||
return buffer.slice(offset, length);
|
||||
return bbslice(buffer, offset, length);
|
||||
}
|
||||
}
|
@ -34,6 +34,8 @@ import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.nio.ReadOnlyBufferException;
|
||||
|
||||
import static io.netty.buffer.api.internal.Statics.bbput;
|
||||
import static io.netty.buffer.api.internal.Statics.bbslice;
|
||||
import static io.netty.buffer.api.internal.Statics.bufferIsClosed;
|
||||
import static io.netty.buffer.api.internal.Statics.bufferIsReadOnly;
|
||||
|
||||
@ -64,7 +66,7 @@ class NioBuffer extends RcSupport<Buffer, NioBuffer> implements Buffer, Readable
|
||||
super(new MakeInaccisbleOnDrop(new ArcDrop<>(ArcDrop.acquire(parent.unsafeGetDrop()))));
|
||||
control = parent.control;
|
||||
base = parent.base;
|
||||
rmem = parent.rmem.slice(0, parent.rmem.capacity()); // Need to slice to get independent byte orders.
|
||||
rmem = bbslice(parent.rmem, 0, parent.rmem.capacity()); // Need to slice to get independent byte orders.
|
||||
assert parent.wmem == CLOSED_BUFFER;
|
||||
wmem = CLOSED_BUFFER;
|
||||
roff = parent.roff;
|
||||
@ -193,7 +195,7 @@ class NioBuffer extends RcSupport<Buffer, NioBuffer> implements Buffer, Readable
|
||||
if (!isAccessible()) {
|
||||
throw new IllegalStateException("This buffer is closed: " + this + '.');
|
||||
}
|
||||
ByteBuffer slice = rmem.slice(offset, length);
|
||||
ByteBuffer slice = bbslice(rmem, offset, length);
|
||||
ArcDrop<NioBuffer> drop = (ArcDrop<NioBuffer>) unsafeGetDrop();
|
||||
drop.increment();
|
||||
Buffer sliceBuffer = new NioBuffer(base, slice, control, drop)
|
||||
@ -226,7 +228,7 @@ class NioBuffer extends RcSupport<Buffer, NioBuffer> implements Buffer, Readable
|
||||
"srcPos = " + srcPos + ", length = " + length + '.');
|
||||
}
|
||||
dest = dest.duplicate().clear();
|
||||
dest.put(destPos, rmem, srcPos, length);
|
||||
bbput(dest, destPos, rmem, srcPos, length);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -453,12 +455,13 @@ class NioBuffer extends RcSupport<Buffer, NioBuffer> implements Buffer, Readable
|
||||
}
|
||||
var drop = (ArcDrop<NioBuffer>) unsafeGetDrop();
|
||||
unsafeSetDrop(new ArcDrop<>(drop));
|
||||
var splitByteBuffer = rmem.slice(0, splitOffset);
|
||||
var splitByteBuffer = bbslice(rmem, 0, splitOffset);
|
||||
// TODO maybe incrementing the existing ArcDrop is enough; maybe we don't need to wrap it in another ArcDrop.
|
||||
var splitBuffer = new NioBuffer(base, splitByteBuffer, control, new ArcDrop<>(drop.increment()));
|
||||
splitBuffer.woff = Math.min(woff, splitOffset);
|
||||
splitBuffer.roff = Math.min(roff, splitOffset);
|
||||
splitBuffer.order(order());
|
||||
ByteOrder order = order();
|
||||
splitBuffer.order(order);
|
||||
boolean readOnly = readOnly();
|
||||
if (readOnly) {
|
||||
splitBuffer.makeReadOnly();
|
||||
@ -466,12 +469,13 @@ class NioBuffer extends RcSupport<Buffer, NioBuffer> implements Buffer, Readable
|
||||
// Note that split, unlike slice, does not deconstify, because data changes in either buffer are not visible
|
||||
// in the other. The split buffers can later deconstify independently if needed.
|
||||
splitBuffer.constBuffer = constBuffer;
|
||||
rmem = rmem.slice(splitOffset, rmem.capacity() - splitOffset);
|
||||
rmem = bbslice(rmem, splitOffset, rmem.capacity() - splitOffset);
|
||||
if (!readOnly) {
|
||||
wmem = rmem;
|
||||
}
|
||||
woff = Math.max(woff, splitOffset) - splitOffset;
|
||||
roff = Math.max(roff, splitOffset) - splitOffset;
|
||||
order(order);
|
||||
return splitBuffer;
|
||||
}
|
||||
|
||||
@ -534,7 +538,7 @@ class NioBuffer extends RcSupport<Buffer, NioBuffer> implements Buffer, Readable
|
||||
|
||||
@Override
|
||||
public ByteBuffer readableBuffer() {
|
||||
return rmem.asReadOnlyBuffer().slice(readerOffset(), readableBytes()).order(order());
|
||||
return bbslice(rmem.asReadOnlyBuffer(), readerOffset(), readableBytes()).order(order());
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -564,7 +568,7 @@ class NioBuffer extends RcSupport<Buffer, NioBuffer> implements Buffer, Readable
|
||||
|
||||
@Override
|
||||
public ByteBuffer writableBuffer() {
|
||||
return wmem.slice(writerOffset(), writableBytes()).order(order());
|
||||
return bbslice(wmem, writerOffset(), writableBytes()).order(order());
|
||||
}
|
||||
// </editor-fold>
|
||||
|
@ -17,7 +17,6 @@ package io.netty.buffer.api.internal;
|
||||
|
||||
import io.netty.buffer.api.Drop;
|
||||
|
||||
import java.io.Serial;
|
||||
import java.lang.ref.Cleaner;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
@ -62,7 +61,6 @@ public final class CleanerDrop<T> implements Drop<T> {
|
||||
}
|
||||
|
||||
private static final class GatedRunner<T> extends AtomicReference<T> implements Runnable {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 2685535951915798850L;
|
||||
final Drop<T> drop;
|
||||
|
@ -21,9 +21,12 @@ import io.netty.buffer.api.Drop;
|
||||
import java.lang.invoke.MethodHandles.Lookup;
|
||||
import java.lang.invoke.VarHandle;
|
||||
import java.lang.ref.Cleaner;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.concurrent.atomic.LongAdder;
|
||||
|
||||
public interface Statics {
|
||||
LongAdder MEM_USAGE_NATIVE = new LongAdder();
|
||||
Cleaner CLEANER = Cleaner.create();
|
||||
Drop<Buffer> NO_OP_DROP = new Drop<Buffer>() {
|
||||
@Override
|
||||
@ -69,6 +72,23 @@ public interface Statics {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The ByteBuffer slice-with-offset-and-length method is only available from Java 13 and onwards, but we need to
|
||||
* support Java 11.
|
||||
*/
|
||||
static ByteBuffer bbslice(ByteBuffer buffer, int fromOffset, int length) {
|
||||
return buffer.slice(fromOffset, length);
|
||||
// return buffer.clear().position(fromOffset).limit(fromOffset + length).slice();
|
||||
}
|
||||
|
||||
/**
|
||||
* The ByteBuffer put-buffer-with-offset-and-length method is not available in Java 11.
|
||||
*/
|
||||
static void bbput(ByteBuffer dest, int destPos, ByteBuffer src, int srcPos, int length) {
|
||||
dest.put(destPos, src, srcPos, length);
|
||||
// dest.position(destPos).put(bbslice(src, srcPos, length));
|
||||
}
|
||||
|
||||
static IllegalStateException bufferIsClosed() {
|
||||
return new IllegalStateException("This buffer is closed.");
|
||||
}
|
@ -15,12 +15,12 @@
|
||||
*/
|
||||
package io.netty.buffer.api.pool;
|
||||
|
||||
import io.netty.buffer.api.internal.CleanerDrop;
|
||||
import io.netty.buffer.api.AllocatorControl.UntetheredMemory;
|
||||
import io.netty.buffer.api.Buffer;
|
||||
import io.netty.buffer.api.Drop;
|
||||
import io.netty.buffer.api.MemoryManager;
|
||||
import io.netty.buffer.api.internal.ArcDrop;
|
||||
import io.netty.buffer.api.internal.CleanerDrop;
|
||||
import io.netty.buffer.api.internal.Statics;
|
||||
|
||||
import java.util.PriorityQueue;
|
@ -431,22 +431,22 @@ public class PooledBufferAllocator implements BufferAllocator, BufferAllocatorMe
|
||||
protected void onRemoval(PoolThreadCache threadCache) {
|
||||
threadCache.free();
|
||||
}
|
||||
}
|
||||
|
||||
private static PoolArena leastUsedArena(PoolArena[] arenas) {
|
||||
if (arenas == null || arenas.length == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PoolArena minArena = arenas[0];
|
||||
for (int i = 1; i < arenas.length; i++) {
|
||||
PoolArena arena = arenas[i];
|
||||
if (arena.numThreadCaches.get() < minArena.numThreadCaches.get()) {
|
||||
minArena = arena;
|
||||
}
|
||||
}
|
||||
|
||||
return minArena;
|
||||
static PoolArena leastUsedArena(PoolArena[] arenas) {
|
||||
if (arenas == null || arenas.length == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
PoolArena minArena = arenas[0];
|
||||
for (int i = 1; i < arenas.length; i++) {
|
||||
PoolArena arena = arenas[i];
|
||||
if (arena.numThreadCaches.get() < minArena.numThreadCaches.get()) {
|
||||
minArena = arena;
|
||||
}
|
||||
}
|
||||
|
||||
return minArena;
|
||||
}
|
||||
|
||||
@Override
|
@ -15,7 +15,7 @@
|
||||
*/
|
||||
package io.netty.buffer.api.pool;
|
||||
|
||||
import static io.netty.buffer.api.pool.PoolThreadCache.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* SizeClasses requires {@code pageShifts} to be defined prior to inclusion,
|
||||
@ -79,13 +79,14 @@ import static io.netty.buffer.api.pool.PoolThreadCache.*;
|
||||
* ( 76, 24, 22, 1, yes, no, no)
|
||||
*/
|
||||
abstract class SizeClasses implements SizeClassesMetric {
|
||||
private static final ConcurrentHashMap<SizeClassKey, SizeClassValue> CACHE =
|
||||
new ConcurrentHashMap<SizeClassKey, SizeClassValue>();
|
||||
|
||||
static final int LOG2_QUANTUM = 4;
|
||||
|
||||
private static final int LOG2_SIZE_CLASS_GROUP = 2;
|
||||
private static final int LOG2_MAX_LOOKUP_SIZE = 12;
|
||||
|
||||
private static final int INDEX_IDX = 0;
|
||||
private static final int LOG2GROUP_IDX = 1;
|
||||
private static final int LOG2DELTA_IDX = 2;
|
||||
private static final int NDELTA_IDX = 3;
|
||||
@ -101,20 +102,17 @@ abstract class SizeClasses implements SizeClassesMetric {
|
||||
this.chunkSize = chunkSize;
|
||||
this.directMemoryCacheAlignment = directMemoryCacheAlignment;
|
||||
|
||||
int group = log2(chunkSize) + 1 - LOG2_QUANTUM;
|
||||
|
||||
//generate size classes
|
||||
//[index, log2Group, log2Delta, nDelta, isMultiPageSize, isSubPage, log2DeltaLookup]
|
||||
sizeClasses = new short[group << LOG2_SIZE_CLASS_GROUP][7];
|
||||
nSizes = sizeClasses();
|
||||
|
||||
//generate lookup table
|
||||
sizeIdx2sizeTab = new int[nSizes];
|
||||
pageIdx2sizeTab = new int[nPSizes];
|
||||
idx2SizeTab(sizeIdx2sizeTab, pageIdx2sizeTab);
|
||||
|
||||
size2idxTab = new int[lookupMaxSize >> LOG2_QUANTUM];
|
||||
size2idxTab(size2idxTab);
|
||||
SizeClassValue value = CACHE.computeIfAbsent(
|
||||
new SizeClassKey(pageSize, pageShifts, chunkSize, directMemoryCacheAlignment),
|
||||
SizeClassValue::new);
|
||||
nSizes = value.nSizes;
|
||||
nSubpages = value.nSubpages;
|
||||
nPSizes = value.nPSizes;
|
||||
smallMaxSizeIdx = value.smallMaxSizeIdx;
|
||||
lookupMaxSize = value.lookupMaxSize;
|
||||
pageIdx2sizeTab = value.pageIdx2sizeTab;
|
||||
sizeIdx2sizeTab = value.sizeIdx2sizeTab;
|
||||
size2idxTab = value.size2idxTab;
|
||||
}
|
||||
|
||||
protected final int pageSize;
|
||||
@ -123,15 +121,11 @@ abstract class SizeClasses implements SizeClassesMetric {
|
||||
protected final int directMemoryCacheAlignment;
|
||||
|
||||
final int nSizes;
|
||||
int nSubpages;
|
||||
int nPSizes;
|
||||
|
||||
int smallMaxSizeIdx;
|
||||
|
||||
private int lookupMaxSize;
|
||||
|
||||
private final short[][] sizeClasses;
|
||||
final int nSubpages;
|
||||
final int nPSizes;
|
||||
final int smallMaxSizeIdx;
|
||||
|
||||
private final int lookupMaxSize;
|
||||
private final int[] pageIdx2sizeTab;
|
||||
|
||||
// lookup table for sizeIdx <= smallMaxSizeIdx
|
||||
@ -141,125 +135,6 @@ abstract class SizeClasses implements SizeClassesMetric {
|
||||
// spacing is 1 << LOG2_QUANTUM, so the size of array is lookupMaxclass >> LOG2_QUANTUM
|
||||
private final int[] size2idxTab;
|
||||
|
||||
private int sizeClasses() {
|
||||
int normalMaxSize = -1;
|
||||
|
||||
int index = 0;
|
||||
int size = 0;
|
||||
|
||||
int log2Group = LOG2_QUANTUM;
|
||||
int log2Delta = LOG2_QUANTUM;
|
||||
int ndeltaLimit = 1 << LOG2_SIZE_CLASS_GROUP;
|
||||
|
||||
//First small group, nDelta start at 0.
|
||||
//first size class is 1 << LOG2_QUANTUM
|
||||
int nDelta = 0;
|
||||
while (nDelta < ndeltaLimit) {
|
||||
size = sizeClass(index++, log2Group, log2Delta, nDelta++);
|
||||
}
|
||||
log2Group += LOG2_SIZE_CLASS_GROUP;
|
||||
|
||||
//All remaining groups, nDelta start at 1.
|
||||
while (size < chunkSize) {
|
||||
nDelta = 1;
|
||||
|
||||
while (nDelta <= ndeltaLimit && size < chunkSize) {
|
||||
size = sizeClass(index++, log2Group, log2Delta, nDelta++);
|
||||
normalMaxSize = size;
|
||||
}
|
||||
|
||||
log2Group++;
|
||||
log2Delta++;
|
||||
}
|
||||
|
||||
//chunkSize must be normalMaxSize
|
||||
assert chunkSize == normalMaxSize;
|
||||
|
||||
//return number of size index
|
||||
return index;
|
||||
}
|
||||
|
||||
//calculate size class
|
||||
private int sizeClass(int index, int log2Group, int log2Delta, int nDelta) {
|
||||
short isMultiPageSize;
|
||||
if (log2Delta >= pageShifts) {
|
||||
isMultiPageSize = yes;
|
||||
} else {
|
||||
int pageSize = 1 << pageShifts;
|
||||
int size = (1 << log2Group) + (1 << log2Delta) * nDelta;
|
||||
|
||||
isMultiPageSize = size == size / pageSize * pageSize? yes : no;
|
||||
}
|
||||
|
||||
int log2Ndelta = nDelta == 0? 0 : log2(nDelta);
|
||||
|
||||
byte remove = 1 << log2Ndelta < nDelta? yes : no;
|
||||
|
||||
int log2Size = log2Delta + log2Ndelta == log2Group? log2Group + 1 : log2Group;
|
||||
if (log2Size == log2Group) {
|
||||
remove = yes;
|
||||
}
|
||||
|
||||
short isSubpage = log2Size < pageShifts + LOG2_SIZE_CLASS_GROUP? yes : no;
|
||||
|
||||
int log2DeltaLookup = log2Size < LOG2_MAX_LOOKUP_SIZE ||
|
||||
log2Size == LOG2_MAX_LOOKUP_SIZE && remove == no
|
||||
? log2Delta : no;
|
||||
|
||||
short[] sz = {
|
||||
(short) index, (short) log2Group, (short) log2Delta,
|
||||
(short) nDelta, isMultiPageSize, isSubpage, (short) log2DeltaLookup
|
||||
};
|
||||
|
||||
sizeClasses[index] = sz;
|
||||
int size = (1 << log2Group) + (nDelta << log2Delta);
|
||||
|
||||
if (sz[PAGESIZE_IDX] == yes) {
|
||||
nPSizes++;
|
||||
}
|
||||
if (sz[SUBPAGE_IDX] == yes) {
|
||||
nSubpages++;
|
||||
smallMaxSizeIdx = index;
|
||||
}
|
||||
if (sz[LOG2_DELTA_LOOKUP_IDX] != no) {
|
||||
lookupMaxSize = size;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
private void idx2SizeTab(int[] sizeIdx2sizeTab, int[] pageIdx2sizeTab) {
|
||||
int pageIdx = 0;
|
||||
|
||||
for (int i = 0; i < nSizes; i++) {
|
||||
short[] sizeClass = sizeClasses[i];
|
||||
int log2Group = sizeClass[LOG2GROUP_IDX];
|
||||
int log2Delta = sizeClass[LOG2DELTA_IDX];
|
||||
int nDelta = sizeClass[NDELTA_IDX];
|
||||
|
||||
int size = (1 << log2Group) + (nDelta << log2Delta);
|
||||
sizeIdx2sizeTab[i] = size;
|
||||
|
||||
if (sizeClass[PAGESIZE_IDX] == yes) {
|
||||
pageIdx2sizeTab[pageIdx++] = size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void size2idxTab(int[] size2idxTab) {
|
||||
int idx = 0;
|
||||
int size = 0;
|
||||
|
||||
for (int i = 0; size <= lookupMaxSize; i++) {
|
||||
int log2Delta = sizeClasses[i][LOG2DELTA_IDX];
|
||||
int times = 1 << log2Delta - LOG2_QUANTUM;
|
||||
|
||||
while (size <= lookupMaxSize && times-- > 0) {
|
||||
size2idxTab[idx++] = i;
|
||||
size = idx + 1 << LOG2_QUANTUM;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int sizeIdx2size(int sizeIdx) {
|
||||
return sizeIdx2sizeTab[sizeIdx];
|
||||
@ -318,7 +193,7 @@ abstract class SizeClasses implements SizeClassesMetric {
|
||||
return size2idxTab[size - 1 >> LOG2_QUANTUM];
|
||||
}
|
||||
|
||||
int x = log2((size << 1) - 1);
|
||||
int x = PoolThreadCache.log2((size << 1) - 1);
|
||||
int shift = x < LOG2_SIZE_CLASS_GROUP + LOG2_QUANTUM + 1
|
||||
? 0 : x - (LOG2_SIZE_CLASS_GROUP + LOG2_QUANTUM);
|
||||
|
||||
@ -350,7 +225,7 @@ abstract class SizeClasses implements SizeClassesMetric {
|
||||
return nPSizes;
|
||||
}
|
||||
|
||||
int x = log2((pageSize << 1) - 1);
|
||||
int x = PoolThreadCache.log2((pageSize << 1) - 1);
|
||||
|
||||
int shift = x < LOG2_SIZE_CLASS_GROUP + pageShifts
|
||||
? 0 : x - (LOG2_SIZE_CLASS_GROUP + pageShifts);
|
||||
@ -397,11 +272,207 @@ abstract class SizeClasses implements SizeClassesMetric {
|
||||
}
|
||||
|
||||
private static int normalizeSizeCompute(int size) {
|
||||
int x = log2((size << 1) - 1);
|
||||
int x = PoolThreadCache.log2((size << 1) - 1);
|
||||
int log2Delta = x < LOG2_SIZE_CLASS_GROUP + LOG2_QUANTUM + 1
|
||||
? LOG2_QUANTUM : x - LOG2_SIZE_CLASS_GROUP - 1;
|
||||
int delta = 1 << log2Delta;
|
||||
int delta_mask = delta - 1;
|
||||
return size + delta_mask & ~delta_mask;
|
||||
}
|
||||
|
||||
private static final class SizeClassKey {
|
||||
final int pageSize;
|
||||
final int pageShifts;
|
||||
final int chunkSize;
|
||||
final int directMemoryCacheAlignment;
|
||||
|
||||
private SizeClassKey(int pageSize, int pageShifts, int chunkSize, int directMemoryCacheAlignment) {
|
||||
this.pageSize = pageSize;
|
||||
this.pageShifts = pageShifts;
|
||||
this.chunkSize = chunkSize;
|
||||
this.directMemoryCacheAlignment = directMemoryCacheAlignment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SizeClassKey that = (SizeClassKey) o;
|
||||
|
||||
if (pageSize != that.pageSize) {
|
||||
return false;
|
||||
}
|
||||
if (pageShifts != that.pageShifts) {
|
||||
return false;
|
||||
}
|
||||
if (chunkSize != that.chunkSize) {
|
||||
return false;
|
||||
}
|
||||
return directMemoryCacheAlignment == that.directMemoryCacheAlignment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = pageSize;
|
||||
result = 31 * result + pageShifts;
|
||||
result = 31 * result + chunkSize;
|
||||
result = 31 * result + directMemoryCacheAlignment;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private static final class SizeClassValue {
|
||||
final SizeClassKey key;
|
||||
final int nSizes;
|
||||
int nSubpages;
|
||||
int nPSizes;
|
||||
int smallMaxSizeIdx;
|
||||
int lookupMaxSize;
|
||||
final short[][] sizeClasses;
|
||||
final int[] pageIdx2sizeTab;
|
||||
final int[] sizeIdx2sizeTab;
|
||||
final int[] size2idxTab;
|
||||
|
||||
SizeClassValue(SizeClassKey key) {
|
||||
this.key = key;
|
||||
int group = PoolThreadCache.log2(key.chunkSize) + 1 - LOG2_QUANTUM;
|
||||
|
||||
//generate size classes
|
||||
//[index, log2Group, log2Delta, nDelta, isMultiPageSize, isSubPage, log2DeltaLookup]
|
||||
sizeClasses = new short[group << LOG2_SIZE_CLASS_GROUP][7];
|
||||
nSizes = sizeClasses();
|
||||
|
||||
//generate lookup table
|
||||
sizeIdx2sizeTab = new int[nSizes];
|
||||
pageIdx2sizeTab = new int[nPSizes];
|
||||
idx2SizeTab(sizeIdx2sizeTab, pageIdx2sizeTab);
|
||||
|
||||
size2idxTab = new int[lookupMaxSize >> LOG2_QUANTUM];
|
||||
size2idxTab(size2idxTab);
|
||||
}
|
||||
|
||||
private int sizeClasses() {
|
||||
int normalMaxSize = -1;
|
||||
|
||||
int index = 0;
|
||||
int size = 0;
|
||||
|
||||
int log2Group = LOG2_QUANTUM;
|
||||
int log2Delta = LOG2_QUANTUM;
|
||||
int ndeltaLimit = 1 << LOG2_SIZE_CLASS_GROUP;
|
||||
|
||||
//First small group, nDelta start at 0.
|
||||
//first size class is 1 << LOG2_QUANTUM
|
||||
int nDelta = 0;
|
||||
while (nDelta < ndeltaLimit) {
|
||||
size = sizeClass(index++, log2Group, log2Delta, nDelta++);
|
||||
}
|
||||
log2Group += LOG2_SIZE_CLASS_GROUP;
|
||||
|
||||
//All remaining groups, nDelta start at 1.
|
||||
while (size < key.chunkSize) {
|
||||
nDelta = 1;
|
||||
|
||||
while (nDelta <= ndeltaLimit && size < key.chunkSize) {
|
||||
size = sizeClass(index++, log2Group, log2Delta, nDelta++);
|
||||
normalMaxSize = size;
|
||||
}
|
||||
|
||||
log2Group++;
|
||||
log2Delta++;
|
||||
}
|
||||
|
||||
//chunkSize must be normalMaxSize
|
||||
assert key.chunkSize == normalMaxSize;
|
||||
|
||||
//return number of size index
|
||||
return index;
|
||||
}
|
||||
|
||||
//calculate size class
|
||||
private int sizeClass(int index, int log2Group, int log2Delta, int nDelta) {
|
||||
short isMultiPageSize;
|
||||
if (log2Delta >= key.pageShifts) {
|
||||
isMultiPageSize = yes;
|
||||
} else {
|
||||
int pageSize = 1 << key.pageShifts;
|
||||
int size = (1 << log2Group) + (1 << log2Delta) * nDelta;
|
||||
|
||||
isMultiPageSize = size == size / pageSize * pageSize? yes : no;
|
||||
}
|
||||
|
||||
int log2Ndelta = nDelta == 0? 0 : PoolThreadCache.log2(nDelta);
|
||||
|
||||
byte remove = 1 << log2Ndelta < nDelta? yes : no;
|
||||
|
||||
int log2Size = log2Delta + log2Ndelta == log2Group? log2Group + 1 : log2Group;
|
||||
if (log2Size == log2Group) {
|
||||
remove = yes;
|
||||
}
|
||||
|
||||
short isSubpage = log2Size < key.pageShifts + LOG2_SIZE_CLASS_GROUP? yes : no;
|
||||
|
||||
int log2DeltaLookup = log2Size < LOG2_MAX_LOOKUP_SIZE ||
|
||||
log2Size == LOG2_MAX_LOOKUP_SIZE && remove == no
|
||||
? log2Delta : no;
|
||||
|
||||
short[] sz = {
|
||||
(short) index, (short) log2Group, (short) log2Delta,
|
||||
(short) nDelta, isMultiPageSize, isSubpage, (short) log2DeltaLookup
|
||||
};
|
||||
|
||||
sizeClasses[index] = sz;
|
||||
int size = (1 << log2Group) + (nDelta << log2Delta);
|
||||
|
||||
if (sz[PAGESIZE_IDX] == yes) {
|
||||
nPSizes++;
|
||||
}
|
||||
if (sz[SUBPAGE_IDX] == yes) {
|
||||
nSubpages++;
|
||||
smallMaxSizeIdx = index;
|
||||
}
|
||||
if (sz[LOG2_DELTA_LOOKUP_IDX] != no) {
|
||||
lookupMaxSize = size;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
private void idx2SizeTab(int[] sizeIdx2sizeTab, int[] pageIdx2sizeTab) {
|
||||
int pageIdx = 0;
|
||||
|
||||
for (int i = 0; i < nSizes; i++) {
|
||||
short[] sizeClass = sizeClasses[i];
|
||||
int log2Group = sizeClass[LOG2GROUP_IDX];
|
||||
int log2Delta = sizeClass[LOG2DELTA_IDX];
|
||||
int nDelta = sizeClass[NDELTA_IDX];
|
||||
|
||||
int size = (1 << log2Group) + (nDelta << log2Delta);
|
||||
sizeIdx2sizeTab[i] = size;
|
||||
|
||||
if (sizeClass[PAGESIZE_IDX] == yes) {
|
||||
pageIdx2sizeTab[pageIdx++] = size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void size2idxTab(int[] size2idxTab) {
|
||||
int idx = 0;
|
||||
int size = 0;
|
||||
|
||||
for (int i = 0; size <= lookupMaxSize; i++) {
|
||||
int log2Delta = sizeClasses[i][LOG2DELTA_IDX];
|
||||
int times = 1 << log2Delta - LOG2_QUANTUM;
|
||||
|
||||
while (size <= lookupMaxSize && times-- > 0) {
|
||||
size2idxTab[idx++] = i;
|
||||
size = idx + 1 << LOG2_QUANTUM;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -15,9 +15,9 @@
|
||||
*/
|
||||
package io.netty.buffer.api.unsafe;
|
||||
|
||||
import io.netty.buffer.api.BufferAllocator;
|
||||
import io.netty.buffer.api.AllocatorControl;
|
||||
import io.netty.buffer.api.Buffer;
|
||||
import io.netty.buffer.api.BufferAllocator;
|
||||
import io.netty.buffer.api.ByteCursor;
|
||||
import io.netty.buffer.api.Drop;
|
||||
import io.netty.buffer.api.Owned;
|
||||
@ -34,6 +34,7 @@ import java.lang.ref.Reference;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import static io.netty.buffer.api.internal.Statics.bbslice;
|
||||
import static io.netty.buffer.api.internal.Statics.bufferIsClosed;
|
||||
import static io.netty.buffer.api.internal.Statics.bufferIsReadOnly;
|
||||
import static io.netty.util.internal.PlatformDependent.BIG_ENDIAN_NATIVE_ORDER;
|
||||
@ -596,7 +597,7 @@ class UnsafeBuffer extends RcSupport<Buffer, UnsafeBuffer> implements Buffer, Re
|
||||
public ByteBuffer readableBuffer() {
|
||||
final ByteBuffer buf;
|
||||
if (hasReadableArray()) {
|
||||
buf = ByteBuffer.wrap(readableArray()).slice(readableArrayOffset(), readableArrayLength());
|
||||
buf = bbslice(ByteBuffer.wrap(readableArray()), readableArrayOffset(), readableArrayLength());
|
||||
} else {
|
||||
buf = PlatformDependent.directBuffer(address + roff, readableBytes());
|
||||
}
|
||||
@ -640,7 +641,7 @@ class UnsafeBuffer extends RcSupport<Buffer, UnsafeBuffer> implements Buffer, Re
|
||||
public ByteBuffer writableBuffer() {
|
||||
final ByteBuffer buf;
|
||||
if (hasWritableArray()) {
|
||||
buf = ByteBuffer.wrap(writableArray()).slice(writableArrayOffset(), writableArrayLength());
|
||||
buf = bbslice(ByteBuffer.wrap(writableArray()), writableArrayOffset(), writableArrayLength());
|
||||
} else {
|
||||
buf = PlatformDependent.directBuffer(address + woff, writableBytes());
|
||||
}
|
43
buffer-api/src/main/java/module-info.java
Normal file
43
buffer-api/src/main/java/module-info.java
Normal file
@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 2021 The Netty Project
|
||||
*
|
||||
* The Netty Project 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:
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
import io.netty.buffer.api.MemoryManagers;
|
||||
import io.netty.buffer.api.bytebuffer.ByteBufferMemoryManagers;
|
||||
import io.netty.buffer.api.unsafe.UnsafeMemoryManagers;
|
||||
|
||||
module netty.incubator.buffer {
|
||||
requires io.netty.common;
|
||||
requires io.netty.buffer;
|
||||
|
||||
// Optional dependencies, needed for some examples.
|
||||
requires static java.logging;//todo remove
|
||||
|
||||
exports io.netty.buffer.api;
|
||||
exports io.netty.buffer.api.adaptor;
|
||||
|
||||
exports io.netty.buffer.api.internal to
|
||||
netty.incubator.buffer.memseg,
|
||||
netty.incubator.buffer.tests;
|
||||
|
||||
uses MemoryManagers;
|
||||
|
||||
// Permit reflective access to non-public members.
|
||||
// Also means we don't have to make all test methods etc. public for JUnit to access them.
|
||||
opens io.netty.buffer.api;//todo remove
|
||||
|
||||
provides MemoryManagers with
|
||||
ByteBufferMemoryManagers,
|
||||
UnsafeMemoryManagers;
|
||||
}
|
72
buffer-memseg/pom.xml
Normal file
72
buffer-memseg/pom.xml
Normal file
@ -0,0 +1,72 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>io.netty.incubator</groupId>
|
||||
<artifactId>netty-incubator-buffer-parent</artifactId>
|
||||
<version>0.0.1.Final-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>netty-incubator-buffer-memseg</artifactId>
|
||||
<version>0.0.1.Final-SNAPSHOT</version>
|
||||
<name>Netty/Incubator/Buffer MemorySegment</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.netty.incubator</groupId>
|
||||
<artifactId>netty-incubator-buffer-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-common</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-buffer</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjdk.jmh</groupId>
|
||||
<artifactId>jmh-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjdk.jmh</groupId>
|
||||
<artifactId>jmh-generator-annprocess</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<version>3.8.1</version>
|
||||
<configuration>
|
||||
<compilerVersion>${java.version}</compilerVersion>
|
||||
<fork>true</fork>
|
||||
<source>${java.compatibility}</source>
|
||||
<target>${java.compatibility}</target>
|
||||
<release>${java.version}</release>
|
||||
<debug>true</debug>
|
||||
<optimize>true</optimize>
|
||||
<showDeprecation>true</showDeprecation>
|
||||
<showWarnings>true</showWarnings>
|
||||
<compilerArgument>-Xlint:-options</compilerArgument>
|
||||
<meminitial>256m</meminitial>
|
||||
<maxmem>1024m</maxmem>
|
||||
<compilerArgs>
|
||||
<arg>--add-modules</arg>
|
||||
<arg>jdk.incubator.foreign</arg>
|
||||
</compilerArgs>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
@ -15,23 +15,22 @@
|
||||
*/
|
||||
package io.netty.buffer.api.memseg;
|
||||
|
||||
import io.netty.buffer.api.internal.ArcDrop;
|
||||
import io.netty.buffer.api.internal.Statics;
|
||||
import io.netty.buffer.api.AllocatorControl;
|
||||
import io.netty.buffer.api.Buffer;
|
||||
import io.netty.buffer.api.Drop;
|
||||
import io.netty.buffer.api.MemoryManager;
|
||||
import io.netty.buffer.api.internal.ArcDrop;
|
||||
import jdk.incubator.foreign.MemorySegment;
|
||||
import jdk.incubator.foreign.ResourceScope;
|
||||
|
||||
import java.lang.ref.Cleaner;
|
||||
|
||||
import static io.netty.buffer.api.internal.Statics.convert;
|
||||
|
||||
public abstract class AbstractMemorySegmentManager implements MemoryManager {
|
||||
@Override
|
||||
public Buffer allocateShared(AllocatorControl allocatorControl, long size, Drop<Buffer> drop, Cleaner cleaner) {
|
||||
var segment = createSegment(size, cleaner);
|
||||
return new MemSegBuffer(segment, segment, convert(drop), allocatorControl);
|
||||
return new MemSegBuffer(segment, segment, Statics.convert(drop), allocatorControl);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -45,7 +44,7 @@ public abstract class AbstractMemorySegmentManager implements MemoryManager {
|
||||
|
||||
@Override
|
||||
public Drop<Buffer> drop() {
|
||||
return convert(MemSegBuffer.SEGMENT_CLOSE);
|
||||
return Statics.convert(MemSegBuffer.SEGMENT_CLOSE);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -71,7 +70,7 @@ public abstract class AbstractMemorySegmentManager implements MemoryManager {
|
||||
@Override
|
||||
public Buffer recoverMemory(AllocatorControl allocatorControl, Object recoverableMemory, Drop<Buffer> drop) {
|
||||
var segment = (MemorySegment) recoverableMemory;
|
||||
return new MemSegBuffer(segment, segment, convert(ArcDrop.acquire(drop)), allocatorControl);
|
||||
return new MemSegBuffer(segment, segment, Statics.convert(ArcDrop.acquire(drop)), allocatorControl);
|
||||
}
|
||||
|
||||
@Override
|
@ -17,6 +17,11 @@ package io.netty.buffer.api.memseg;
|
||||
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.api.BufferAllocator;
|
||||
import io.netty.buffer.api.adaptor.BufferIntegratable;
|
||||
import io.netty.buffer.api.adaptor.ByteBufAdaptor;
|
||||
import io.netty.buffer.api.adaptor.ByteBufAllocatorAdaptor;
|
||||
import io.netty.buffer.api.internal.ArcDrop;
|
||||
import io.netty.buffer.api.internal.Statics;
|
||||
import io.netty.buffer.api.AllocatorControl;
|
||||
import io.netty.buffer.api.Buffer;
|
||||
import io.netty.buffer.api.ByteCursor;
|
||||
@ -27,19 +32,12 @@ import io.netty.buffer.api.WritableComponentProcessor;
|
||||
import io.netty.buffer.api.Drop;
|
||||
import io.netty.buffer.api.Owned;
|
||||
import io.netty.buffer.api.RcSupport;
|
||||
import io.netty.buffer.api.adaptor.BufferIntegratable;
|
||||
import io.netty.buffer.api.adaptor.ByteBufAdaptor;
|
||||
import io.netty.buffer.api.adaptor.ByteBufAllocatorAdaptor;
|
||||
import io.netty.buffer.api.internal.ArcDrop;
|
||||
import io.netty.buffer.api.internal.Statics;
|
||||
import jdk.incubator.foreign.MemorySegment;
|
||||
import jdk.incubator.foreign.ResourceScope;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import static io.netty.buffer.api.internal.Statics.bufferIsClosed;
|
||||
import static io.netty.buffer.api.internal.Statics.bufferIsReadOnly;
|
||||
import static jdk.incubator.foreign.MemoryAccess.getByteAtOffset;
|
||||
import static jdk.incubator.foreign.MemoryAccess.getCharAtOffset;
|
||||
import static jdk.incubator.foreign.MemoryAccess.getDoubleAtOffset;
|
||||
@ -56,7 +54,7 @@ import static jdk.incubator.foreign.MemoryAccess.setLongAtOffset;
|
||||
import static jdk.incubator.foreign.MemoryAccess.setShortAtOffset;
|
||||
|
||||
class MemSegBuffer extends RcSupport<Buffer, MemSegBuffer> implements Buffer, ReadableComponent, WritableComponent,
|
||||
BufferIntegratable {
|
||||
BufferIntegratable {
|
||||
private static final MemorySegment CLOSED_SEGMENT;
|
||||
static final Drop<MemSegBuffer> SEGMENT_CLOSE;
|
||||
|
||||
@ -325,7 +323,7 @@ class MemSegBuffer extends RcSupport<Buffer, MemSegBuffer> implements Buffer, Re
|
||||
|
||||
private void copyInto(int srcPos, MemorySegment dest, int destPos, int length) {
|
||||
if (seg == CLOSED_SEGMENT) {
|
||||
throw bufferIsClosed();
|
||||
throw Statics.bufferIsClosed();
|
||||
}
|
||||
if (srcPos < 0) {
|
||||
throw new IllegalArgumentException("The srcPos cannot be negative: " + srcPos + '.');
|
||||
@ -360,7 +358,7 @@ class MemSegBuffer extends RcSupport<Buffer, MemSegBuffer> implements Buffer, Re
|
||||
@Override
|
||||
public ByteCursor openCursor(int fromOffset, int length) {
|
||||
if (seg == CLOSED_SEGMENT) {
|
||||
throw bufferIsClosed();
|
||||
throw Statics.bufferIsClosed();
|
||||
}
|
||||
if (fromOffset < 0) {
|
||||
throw new IllegalArgumentException("The fromOffset cannot be negative: " + fromOffset + '.');
|
||||
@ -430,7 +428,7 @@ class MemSegBuffer extends RcSupport<Buffer, MemSegBuffer> implements Buffer, Re
|
||||
@Override
|
||||
public ByteCursor openReverseCursor(int fromOffset, int length) {
|
||||
if (seg == CLOSED_SEGMENT) {
|
||||
throw bufferIsClosed();
|
||||
throw Statics.bufferIsClosed();
|
||||
}
|
||||
if (fromOffset < 0) {
|
||||
throw new IllegalArgumentException("The fromOffset cannot be negative: " + fromOffset + '.');
|
||||
@ -508,7 +506,7 @@ class MemSegBuffer extends RcSupport<Buffer, MemSegBuffer> implements Buffer, Re
|
||||
throw new IllegalArgumentException("The minimum growth cannot be negative: " + minimumGrowth + '.');
|
||||
}
|
||||
if (seg != wseg) {
|
||||
throw bufferIsReadOnly();
|
||||
throw Statics.bufferIsReadOnly();
|
||||
}
|
||||
if (writableBytes() >= size) {
|
||||
// We already have enough space.
|
||||
@ -1172,27 +1170,27 @@ class MemSegBuffer extends RcSupport<Buffer, MemSegBuffer> implements Buffer, Re
|
||||
|
||||
private RuntimeException checkWriteState(IndexOutOfBoundsException ioobe) {
|
||||
if (seg == CLOSED_SEGMENT) {
|
||||
return bufferIsClosed();
|
||||
return Statics.bufferIsClosed();
|
||||
}
|
||||
if (wseg != seg) {
|
||||
return bufferIsReadOnly();
|
||||
return Statics.bufferIsReadOnly();
|
||||
}
|
||||
return ioobe;
|
||||
}
|
||||
|
||||
private RuntimeException readAccessCheckException(int index) {
|
||||
if (seg == CLOSED_SEGMENT) {
|
||||
throw bufferIsClosed();
|
||||
throw Statics.bufferIsClosed();
|
||||
}
|
||||
return outOfBounds(index);
|
||||
}
|
||||
|
||||
private RuntimeException writeAccessCheckException(int index) {
|
||||
if (seg == CLOSED_SEGMENT) {
|
||||
throw bufferIsClosed();
|
||||
throw Statics.bufferIsClosed();
|
||||
}
|
||||
if (wseg != seg) {
|
||||
return bufferIsReadOnly();
|
||||
return Statics.bufferIsReadOnly();
|
||||
}
|
||||
return outOfBounds(index);
|
||||
}
|
@ -15,18 +15,17 @@
|
||||
*/
|
||||
package io.netty.buffer.api.memseg;
|
||||
|
||||
import io.netty.buffer.api.internal.Statics;
|
||||
import jdk.incubator.foreign.MemorySegment;
|
||||
import jdk.incubator.foreign.ResourceScope;
|
||||
|
||||
import java.lang.ref.Cleaner;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.atomic.LongAdder;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static jdk.incubator.foreign.ResourceScope.newSharedScope;
|
||||
|
||||
public class NativeMemorySegmentManager extends AbstractMemorySegmentManager {
|
||||
public static final LongAdder MEM_USAGE_NATIVE = new LongAdder();
|
||||
private static final ConcurrentHashMap<Long, Runnable> CLEANUP_ACTIONS = new ConcurrentHashMap<>();
|
||||
private static final Function<Long, Runnable> CLEANUP_ACTION_MAKER = s -> new ReduceNativeMemoryUsage(s);
|
||||
|
||||
@ -43,7 +42,7 @@ public class NativeMemorySegmentManager extends AbstractMemorySegmentManager {
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
MEM_USAGE_NATIVE.add(-size);
|
||||
Statics.MEM_USAGE_NATIVE.add(-size);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -62,7 +61,7 @@ public class NativeMemorySegmentManager extends AbstractMemorySegmentManager {
|
||||
final ResourceScope scope = cleaner == null ? newSharedScope() : newSharedScope(cleaner);
|
||||
scope.addCloseAction(getCleanupAction(size));
|
||||
var segment = MemorySegment.allocateNative(size, scope);
|
||||
MEM_USAGE_NATIVE.add(size);
|
||||
Statics.MEM_USAGE_NATIVE.add(size);
|
||||
return segment;
|
||||
}
|
||||
}
|
@ -13,25 +13,22 @@
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
module netty.incubator.buffer {
|
||||
import io.netty.buffer.api.MemoryManagers;
|
||||
import io.netty.buffer.api.memseg.SegmentMemoryManagers;
|
||||
|
||||
module netty.incubator.buffer.memseg {
|
||||
requires jdk.incubator.foreign;
|
||||
requires io.netty.common;
|
||||
requires io.netty.buffer;
|
||||
requires netty.incubator.buffer;
|
||||
|
||||
// Optional dependencies, needed for some examples.
|
||||
requires static java.logging;
|
||||
|
||||
exports io.netty.buffer.api;
|
||||
exports io.netty.buffer.api.adaptor;
|
||||
|
||||
uses io.netty.buffer.api.MemoryManagers;
|
||||
|
||||
// Permit reflective access to non-public members.
|
||||
// Also means we don't have to make all test methods etc. public for JUnit to access them.
|
||||
opens io.netty.buffer.api;
|
||||
opens io.netty.buffer.api.memseg;
|
||||
|
||||
provides io.netty.buffer.api.MemoryManagers with
|
||||
io.netty.buffer.api.memseg.SegmentMemoryManagers,
|
||||
io.netty.buffer.api.bytebuffer.ByteBufferMemoryManagers,
|
||||
io.netty.buffer.api.unsafe.UnsafeMemoryManagers;
|
||||
provides MemoryManagers with
|
||||
SegmentMemoryManagers;
|
||||
}
|
@ -13,7 +13,7 @@
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.buffer.api.benchmarks;
|
||||
package io.netty.buffer.api.memseg.benchmarks;
|
||||
|
||||
import io.netty.buffer.api.BufferAllocator;
|
||||
import io.netty.buffer.api.Buffer;
|
@ -13,7 +13,7 @@
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.buffer.api.benchmarks;
|
||||
package io.netty.buffer.api.memseg.benchmarks;
|
||||
|
||||
import jdk.incubator.foreign.MemorySegment;
|
||||
import jdk.incubator.foreign.ResourceScope;
|
@ -13,10 +13,12 @@
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.buffer.api.benchmarks;
|
||||
package io.netty.buffer.api.memseg.benchmarks;
|
||||
|
||||
import io.netty.buffer.api.BufferAllocator;
|
||||
import io.netty.buffer.api.memseg.SegmentMemoryManagers;
|
||||
import io.netty.buffer.api.Buffer;
|
||||
import io.netty.buffer.api.MemoryManagers;
|
||||
import org.openjdk.jmh.annotations.Benchmark;
|
||||
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||
import org.openjdk.jmh.annotations.Fork;
|
||||
@ -41,10 +43,37 @@ import static java.util.concurrent.CompletableFuture.completedFuture;
|
||||
@OutputTimeUnit(TimeUnit.MICROSECONDS)
|
||||
@State(Scope.Benchmark)
|
||||
public class MemorySegmentClosedByCleanerBenchmark {
|
||||
private static final BufferAllocator heap = BufferAllocator.heap();
|
||||
private static final BufferAllocator heapPooled = BufferAllocator.pooledHeap();
|
||||
private static final BufferAllocator direct = BufferAllocator.direct();
|
||||
private static final BufferAllocator directPooled = BufferAllocator.pooledDirect();
|
||||
private static final BufferAllocator heap;
|
||||
private static final BufferAllocator heapPooled;
|
||||
private static final BufferAllocator direct;
|
||||
private static final BufferAllocator directPooled;
|
||||
|
||||
static {
|
||||
class Allocators {
|
||||
final BufferAllocator heap;
|
||||
final BufferAllocator pooledHeap;
|
||||
final BufferAllocator direct;
|
||||
final BufferAllocator pooledDirect;
|
||||
|
||||
Allocators(BufferAllocator heap, BufferAllocator pooledHeap,
|
||||
BufferAllocator direct, BufferAllocator pooledDirect) {
|
||||
this.heap = heap;
|
||||
this.pooledHeap = pooledHeap;
|
||||
this.direct = direct;
|
||||
this.pooledDirect = pooledDirect;
|
||||
}
|
||||
}
|
||||
|
||||
var allocs = MemoryManagers.using(new SegmentMemoryManagers(), () -> {
|
||||
return new Allocators(BufferAllocator.heap(), BufferAllocator.pooledHeap(),
|
||||
BufferAllocator.direct(), BufferAllocator.pooledDirect());
|
||||
});
|
||||
|
||||
heap = allocs.heap;
|
||||
heapPooled = allocs.pooledHeap;
|
||||
direct = allocs.direct;
|
||||
directPooled = allocs.pooledDirect;
|
||||
}
|
||||
|
||||
@Param({"heavy", "light"})
|
||||
public String workload;
|
96
buffer-tests/pom.xml
Normal file
96
buffer-tests/pom.xml
Normal file
@ -0,0 +1,96 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>io.netty.incubator</groupId>
|
||||
<artifactId>netty-incubator-buffer-parent</artifactId>
|
||||
<version>0.0.1.Final-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>netty-incubator-buffer-tests</artifactId>
|
||||
<version>0.0.1.Final-SNAPSHOT</version>
|
||||
<name>Netty/Incubator/Buffer Tests</name>
|
||||
<packaging>jar</packaging>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.netty.incubator</groupId>
|
||||
<artifactId>netty-incubator-buffer-api</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-api</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-engine</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter-params</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.vintage</groupId>
|
||||
<artifactId>junit-vintage-engine</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.assertj</groupId>
|
||||
<artifactId>assertj-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-core</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-build-common</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-handler</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.netty</groupId>
|
||||
<artifactId>netty-codec-http</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjdk.jmh</groupId>
|
||||
<artifactId>jmh-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.openjdk.jmh</groupId>
|
||||
<artifactId>jmh-generator-annprocess</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>Java 17 support</id>
|
||||
<activation>
|
||||
<jdk>17</jdk>
|
||||
</activation>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>io.netty.incubator</groupId>
|
||||
<artifactId>netty-incubator-buffer-memseg</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
25
buffer-tests/src/main/java/module-info.java
Normal file
25
buffer-tests/src/main/java/module-info.java
Normal file
@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2021 The Netty Project
|
||||
*
|
||||
* The Netty Project 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:
|
||||
*
|
||||
* https://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.
|
||||
*/
|
||||
open module netty.incubator.buffer.tests {
|
||||
requires io.netty.common;
|
||||
requires io.netty.buffer;
|
||||
|
||||
// Optional dependencies, needed for some examples.
|
||||
requires static java.logging;
|
||||
|
||||
requires netty.incubator.buffer;
|
||||
requires static netty.incubator.buffer.memseg;
|
||||
}
|
@ -13,8 +13,12 @@
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.buffer.api;
|
||||
package io.netty.buffer.api.tests;
|
||||
|
||||
import io.netty.buffer.api.Buffer;
|
||||
import io.netty.buffer.api.BufferAllocator;
|
||||
import io.netty.buffer.api.CompositeBuffer;
|
||||
import io.netty.buffer.api.Scope;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
@ -13,8 +13,10 @@
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.buffer.api;
|
||||
package io.netty.buffer.api.tests;
|
||||
|
||||
import io.netty.buffer.api.Buffer;
|
||||
import io.netty.buffer.api.BufferAllocator;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
@ -13,8 +13,10 @@
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.buffer.api;
|
||||
package io.netty.buffer.api.tests;
|
||||
|
||||
import io.netty.buffer.api.Buffer;
|
||||
import io.netty.buffer.api.BufferAllocator;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
@ -13,13 +13,17 @@
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.buffer.api;
|
||||
package io.netty.buffer.api.tests;
|
||||
|
||||
import io.netty.buffer.api.memseg.NativeMemorySegmentManager;
|
||||
import io.netty.buffer.api.MemoryManagers;
|
||||
import io.netty.buffer.api.internal.Statics;
|
||||
import org.junit.jupiter.api.condition.DisabledForJreRange;
|
||||
import org.junit.jupiter.api.condition.JRE;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static io.netty.buffer.api.MemoryManagers.using;
|
||||
@ -36,21 +40,23 @@ public class BufferCleanerTest extends BufferTestSupport {
|
||||
Stream.Builder<Fixture> builder = Stream.builder();
|
||||
builder.add(new Fixture(f + "/" + managers, () -> using(managers, f), f.getProperties()));
|
||||
return builder.build();
|
||||
}).toList();
|
||||
}).collect(Collectors.toList());
|
||||
return fixtureCombinations(initFixtures).filter(f -> f.isDirect()).toArray(Fixture[]::new);
|
||||
}
|
||||
|
||||
// Only run this one on JDK 17.
|
||||
@DisabledForJreRange(min = JRE.JAVA_11, max = JRE.JAVA_16)
|
||||
@ParameterizedTest
|
||||
@MethodSource("memorySegmentAllocators")
|
||||
public void bufferMustBeClosedByCleaner(Fixture fixture) throws InterruptedException {
|
||||
var initial = NativeMemorySegmentManager.MEM_USAGE_NATIVE.sum();
|
||||
var initial = Statics.MEM_USAGE_NATIVE.sum();
|
||||
int allocationSize = 1024;
|
||||
allocateAndForget(fixture, allocationSize);
|
||||
long sum = 0;
|
||||
for (int i = 0; i < 15; i++) {
|
||||
System.gc();
|
||||
System.runFinalization();
|
||||
sum = NativeMemorySegmentManager.MEM_USAGE_NATIVE.sum() - initial;
|
||||
sum = Statics.MEM_USAGE_NATIVE.sum() - initial;
|
||||
if (sum < allocationSize) {
|
||||
// The memory must have been cleaned.
|
||||
return;
|
@ -13,8 +13,10 @@
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.buffer.api;
|
||||
package io.netty.buffer.api.tests;
|
||||
|
||||
import io.netty.buffer.api.Buffer;
|
||||
import io.netty.buffer.api.BufferAllocator;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
@ -13,8 +13,12 @@
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.buffer.api;
|
||||
package io.netty.buffer.api.tests;
|
||||
|
||||
import io.netty.buffer.api.Buffer;
|
||||
import io.netty.buffer.api.BufferAllocator;
|
||||
import io.netty.buffer.api.ByteCursor;
|
||||
import io.netty.buffer.api.CompositeBuffer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
@ -13,8 +13,11 @@
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.buffer.api;
|
||||
package io.netty.buffer.api.tests;
|
||||
|
||||
import io.netty.buffer.api.Buffer;
|
||||
import io.netty.buffer.api.BufferAllocator;
|
||||
import io.netty.buffer.api.CompositeBuffer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
@ -13,8 +13,10 @@
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.buffer.api;
|
||||
package io.netty.buffer.api.tests;
|
||||
|
||||
import io.netty.buffer.api.Buffer;
|
||||
import io.netty.buffer.api.BufferAllocator;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
@ -13,8 +13,11 @@
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.buffer.api;
|
||||
package io.netty.buffer.api.tests;
|
||||
|
||||
import io.netty.buffer.api.Buffer;
|
||||
import io.netty.buffer.api.BufferAllocator;
|
||||
import io.netty.buffer.api.CompositeBuffer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
@ -13,8 +13,10 @@
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.buffer.api;
|
||||
package io.netty.buffer.api.tests;
|
||||
|
||||
import io.netty.buffer.api.Buffer;
|
||||
import io.netty.buffer.api.BufferAllocator;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
@ -13,8 +13,10 @@
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.buffer.api;
|
||||
package io.netty.buffer.api.tests;
|
||||
|
||||
import io.netty.buffer.api.Buffer;
|
||||
import io.netty.buffer.api.BufferAllocator;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
@ -13,8 +13,10 @@
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.buffer.api;
|
||||
package io.netty.buffer.api.tests;
|
||||
|
||||
import io.netty.buffer.api.Buffer;
|
||||
import io.netty.buffer.api.BufferAllocator;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
@ -13,8 +13,10 @@
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.buffer.api;
|
||||
package io.netty.buffer.api.tests;
|
||||
|
||||
import io.netty.buffer.api.Buffer;
|
||||
import io.netty.buffer.api.BufferAllocator;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
@ -13,8 +13,10 @@
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.buffer.api;
|
||||
package io.netty.buffer.api.tests;
|
||||
|
||||
import io.netty.buffer.api.Buffer;
|
||||
import io.netty.buffer.api.BufferAllocator;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
@ -13,8 +13,10 @@
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.buffer.api;
|
||||
package io.netty.buffer.api.tests;
|
||||
|
||||
import io.netty.buffer.api.Buffer;
|
||||
import io.netty.buffer.api.BufferAllocator;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
@ -13,8 +13,12 @@
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.buffer.api;
|
||||
package io.netty.buffer.api.tests;
|
||||
|
||||
import io.netty.buffer.api.Buffer;
|
||||
import io.netty.buffer.api.BufferAllocator;
|
||||
import io.netty.buffer.api.CompositeBuffer;
|
||||
import io.netty.buffer.api.Send;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
@ -13,8 +13,12 @@
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.buffer.api;
|
||||
package io.netty.buffer.api.tests;
|
||||
|
||||
import io.netty.buffer.api.Buffer;
|
||||
import io.netty.buffer.api.BufferAllocator;
|
||||
import io.netty.buffer.api.BufferRef;
|
||||
import io.netty.buffer.api.Send;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
@ -13,13 +13,16 @@
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.buffer.api;
|
||||
package io.netty.buffer.api.tests;
|
||||
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import io.netty.buffer.api.Buffer;
|
||||
import io.netty.buffer.api.BufferAllocator;
|
||||
import io.netty.buffer.api.CompositeBuffer;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
||||
|
||||
import java.nio.ByteOrder;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ThreadLocalRandom;
|
||||
|
||||
@ -607,6 +610,23 @@ public class BufferReferenceCountingTest extends BufferTestSupport {
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("allocators")
|
||||
public void splitMustPreserveByteOrder(Fixture fixture) {
|
||||
try (BufferAllocator allocator = fixture.createAllocator()) {
|
||||
try (Buffer a = allocator.allocate(8).order(BIG_ENDIAN);
|
||||
Buffer b = a.split(4)) {
|
||||
assertThat(a.order()).isEqualTo(BIG_ENDIAN);
|
||||
assertThat(b.order()).isEqualTo(BIG_ENDIAN);
|
||||
}
|
||||
try (Buffer a = allocator.allocate(8).order(LITTLE_ENDIAN);
|
||||
Buffer b = a.split(4)) {
|
||||
assertThat(a.order()).isEqualTo(LITTLE_ENDIAN);
|
||||
assertThat(b.order()).isEqualTo(LITTLE_ENDIAN);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@MethodSource("allocators")
|
||||
public void ensureWritableOnSplitBuffers(Fixture fixture) {
|
@ -13,8 +13,12 @@
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package io.netty.buffer.api;
|
||||
package io.netty.buffer.api.tests;
|
||||
|
||||
import io.netty.buffer.api.Buffer;
|
||||
import io.netty.buffer.api.BufferAllocator;
|
||||
import io.netty.buffer.api.BufferRef;
|
||||
import io.netty.buffer.api.Send;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.MethodSource;
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user