1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty5.buffer.api.unsafe;
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.ArcDrop;
25 import io.netty5.buffer.api.internal.Statics;
26 import io.netty5.buffer.api.internal.WrappingAllocation;
27 import io.netty5.util.internal.PlatformDependent;
28 import io.netty5.util.internal.SystemPropertyUtil;
29
30 import java.lang.ref.Cleaner;
31 import java.util.function.Function;
32
33 import static io.netty5.buffer.api.internal.Statics.convert;
34
35
36
37
38
39
40
41
42
43 public final class UnsafeMemoryManager implements MemoryManager {
44 private static final boolean FREE_IMMEDIATELY = SystemPropertyUtil.getBoolean(
45 "io.netty5.buffer.api.unsafe.UnsafeMemoryManager.freeDirectMemoryImmediately", true);
46
47 public UnsafeMemoryManager() {
48 if (!PlatformDependent.hasUnsafe()) {
49 UnsupportedOperationException notSupported = new UnsupportedOperationException("Unsafe is not available.");
50 notSupported.addSuppressed(PlatformDependent.getUnsafeUnavailabilityCause());
51 throw notSupported;
52 }
53 if (!PlatformDependent.hasDirectBufferNoCleanerConstructor()) {
54 throw new UnsupportedOperationException("DirectByteBuffer internal constructor is not available.");
55 }
56 }
57
58 @Override
59 public Buffer allocateShared(AllocatorControl control, long size,
60 Function<Drop<Buffer>, Drop<Buffer>> dropDecorator,
61 AllocationType allocationType) {
62 final Object base;
63 final long address;
64 final UnsafeMemory memory;
65 final int size32 = Math.toIntExact(size);
66 Cleaner cleaner = Statics.CLEANER;
67 Drop<Buffer> drop = Statics.NO_OP_DROP;
68 if (allocationType == StandardAllocationTypes.OFF_HEAP) {
69 base = null;
70 address = PlatformDependent.allocateMemory(size);
71 Statics.MEM_USAGE_NATIVE.add(size);
72 PlatformDependent.setMemory(address, size, (byte) 0);
73 memory = new UnsafeMemory(base, address, size32);
74 FreeAddress freeAddress = new FreeAddress(address, size32);
75 if (FREE_IMMEDIATELY) {
76 drop = ArcDrop.wrap(freeAddress);
77 } else {
78 cleaner.register(memory, freeAddress);
79 }
80 } else if (allocationType == StandardAllocationTypes.ON_HEAP) {
81 base = PlatformDependent.allocateUninitializedArray(size32);
82 address = PlatformDependent.byteArrayBaseOffset();
83 memory = new UnsafeMemory(base, address, size32);
84 } else if (allocationType instanceof WrappingAllocation) {
85 base = ((WrappingAllocation) allocationType).getArray();
86 address = PlatformDependent.byteArrayBaseOffset();
87 memory = new UnsafeMemory(base, address, size32);
88 } else {
89 throw new IllegalArgumentException("Unknown allocation type: " + allocationType);
90 }
91 return createBuffer(memory, size32, control, dropDecorator.apply(drop));
92 }
93
94 @Override
95 public Buffer allocateConstChild(Buffer readOnlyConstParent) {
96 UnsafeBuffer buf = (UnsafeBuffer) readOnlyConstParent;
97 return buf.newConstChild();
98 }
99
100 @Override
101 public Object unwrapRecoverableMemory(Buffer buf) {
102 return ((UnsafeBuffer) buf).recover();
103 }
104
105 @Override
106 public Buffer recoverMemory(AllocatorControl allocatorControl, Object recoverableMemory, Drop<Buffer> drop) {
107 UnsafeMemory memory = (UnsafeMemory) recoverableMemory;
108 int size = memory.size;
109 return createBuffer(memory, size, allocatorControl, drop);
110 }
111
112 private static UnsafeBuffer createBuffer(UnsafeMemory memory, int size, AllocatorControl allocatorControl,
113 Drop<Buffer> drop) {
114 Drop<UnsafeBuffer> concreteDrop = convert(drop);
115 UnsafeBuffer unsafeBuffer = new UnsafeBuffer(memory, 0, size, allocatorControl, concreteDrop);
116 concreteDrop.attach(unsafeBuffer);
117 return unsafeBuffer;
118 }
119
120 @Override
121 public Object sliceMemory(Object memory, int offset, int length) {
122 return ((UnsafeMemory) memory).slice(offset, length);
123 }
124
125 @Override
126 public void clearMemory(Object memory) {
127 ((UnsafeMemory) memory).clearMemory();
128 }
129
130 @Override
131 public String implementationName() {
132 return "Unsafe";
133 }
134 }