View Javadoc
1   /*
2    * Copyright 2021 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.netty5.buffer.api.bytebuffer;
17  
18  import io.netty5.buffer.api.AllocationType;
19  import io.netty5.buffer.api.AllocatorControl;
20  import io.netty5.buffer.api.Buffer;
21  import io.netty5.buffer.api.Drop;
22  import io.netty5.buffer.api.MemoryManager;
23  import io.netty5.buffer.api.StandardAllocationTypes;
24  import io.netty5.buffer.api.internal.Statics;
25  import io.netty5.buffer.api.internal.WrappingAllocation;
26  
27  import java.nio.ByteBuffer;
28  import java.util.function.Function;
29  
30  import static io.netty5.buffer.api.internal.Statics.bbslice;
31  import static io.netty5.buffer.api.internal.Statics.convert;
32  
33  /**
34   * This memory manager produces and manages {@link Buffer} instances that are backed by NIO {@link ByteBuffer}
35   * instances.
36   * <p>
37   * Memory managers are normally not used directly.
38   * Instead, you likely want to use the {@link io.netty5.buffer.api.DefaultBufferAllocators}, or the static methods on
39   * {@link io.netty5.buffer.api.BufferAllocator}.
40   */
41  public final class ByteBufferMemoryManager implements MemoryManager {
42      @Override
43      public Buffer allocateShared(AllocatorControl allocatorControl, long size,
44                                   Function<Drop<Buffer>, Drop<Buffer>> dropDecorator,
45                                   AllocationType allocationType) {
46          int capacity = Math.toIntExact(size);
47          final ByteBuffer buffer;
48          if (allocationType == StandardAllocationTypes.OFF_HEAP) {
49              buffer = ByteBuffer.allocateDirect(capacity);
50          } else if (allocationType == StandardAllocationTypes.ON_HEAP) {
51              buffer = ByteBuffer.allocate(capacity);
52          } else if (allocationType instanceof WrappingAllocation) {
53              buffer = ByteBuffer.wrap(((WrappingAllocation) allocationType).getArray());
54          } else {
55              throw new IllegalArgumentException("Unknown allocation type: " + allocationType);
56          }
57          return createBuffer(buffer, allocatorControl, dropDecorator.apply(drop()));
58      }
59  
60      @Override
61      public Buffer allocateConstChild(Buffer readOnlyConstParent) {
62          NioBuffer buf = (NioBuffer) readOnlyConstParent;
63          return buf.newConstChild();
64      }
65  
66      private static Drop<Buffer> drop() {
67          return Statics.NO_OP_DROP;
68      }
69  
70      @Override
71      public Object unwrapRecoverableMemory(Buffer buf) {
72          return ((NioBuffer) buf).recoverable();
73      }
74  
75      @Override
76      public Buffer recoverMemory(AllocatorControl allocatorControl, Object recoverableMemory, Drop<Buffer> drop) {
77          ByteBuffer memory = (ByteBuffer) recoverableMemory;
78          return createBuffer(memory, allocatorControl, drop);
79      }
80  
81      private static NioBuffer createBuffer(ByteBuffer memory, AllocatorControl allocatorControl, Drop<Buffer> drop) {
82          Drop<NioBuffer> concreteDrop = convert(drop);
83          NioBuffer nioBuffer = new NioBuffer(memory, memory, allocatorControl, concreteDrop);
84          concreteDrop.attach(nioBuffer);
85          return nioBuffer;
86      }
87  
88      @Override
89      public Object sliceMemory(Object memory, int offset, int length) {
90          var buffer = (ByteBuffer) memory;
91          return bbslice(buffer, offset, length);
92      }
93  
94      @Override
95      public void clearMemory(Object memory) {
96          ByteBuffer buffer = (ByteBuffer) memory;
97          Statics.setMemory(buffer, buffer.capacity(), (byte) 0);
98      }
99  
100     @Override
101     public String implementationName() {
102         return "ByteBuffer";
103     }
104 }