1 /*
2 * Copyright 2025 The Netty Project
3 *
4 * The Netty Project licenses this file to you under the Apache License,
5 * version 2.0 (the "License"); you may not use this file except in compliance
6 * with the License. You may obtain a copy of the License at:
7 *
8 * https://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13 * License for the specific language governing permissions and limitations
14 * under the License.
15 */
16 package io.netty.channel.uring;
17
18 import io.netty.buffer.ByteBuf;
19 import io.netty.buffer.ByteBufAllocator;
20
21 import java.util.Objects;
22 import java.util.function.Consumer;
23
24 /**
25 * Base class for {@link IoUringBufferRingAllocator} implementations which support large allocations.
26 */
27 public abstract class AbstractIoUringBufferRingAllocator implements IoUringBufferRingAllocator {
28 private final ByteBufAllocator allocator;
29 private final boolean largeAllocation;
30
31 /**
32 * Creates new instance.
33 *
34 * @param allocator the {@link ByteBufAllocator} to use for the allocations
35 * @param largeAllocation {@code true} if we should do a large allocation for the whole buffer ring
36 * and then slice out the buffers or {@code false} if we should do one allocation
37 * per buffer.
38 */
39 protected AbstractIoUringBufferRingAllocator(ByteBufAllocator allocator, boolean largeAllocation) {
40 this.allocator = Objects.requireNonNull(allocator, "allocator");
41 this.largeAllocation = largeAllocation;
42 }
43
44 @Override
45 public final void allocateBatch(Consumer<ByteBuf> consumer, int number) {
46 if (largeAllocation) {
47 int bufferSize = nextBufferSize();
48 ByteBuf buffer = allocator.directBuffer(nextBufferSize() * number);
49 try {
50 for (int i = 0; i < number; i++) {
51 consumer.accept(buffer
52 .retainedSlice(i * bufferSize, bufferSize)
53 .setIndex(0, 0)
54 );
55 }
56 } finally {
57 buffer.release();
58 }
59 } else {
60 IoUringBufferRingAllocator.super.allocateBatch(consumer, number);
61 }
62 }
63
64 @Override
65 public final ByteBuf allocate() {
66 return allocator.directBuffer(nextBufferSize());
67 }
68
69 /**
70 * Does nothing by default, sub-classes might override this.
71 *
72 * @param attempted the attempted bytes to read.
73 * @param actual the number of bytes that could be read.
74 */
75 @Override
76 public void lastBytesRead(int attempted, int actual) {
77 // NOOP.
78 }
79
80 /**
81 * Return the next buffer size of each {@link ByteBuf} that is put into the buffer ring.
82 *
83 * @return the next size.
84 */
85 protected abstract int nextBufferSize();
86 }