1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.netty.buffer;
18
19 import io.netty.util.Recycler;
20
21 import java.nio.ByteBuffer;
22 import java.nio.ByteOrder;
23
24 abstract class PooledByteBuf<T> extends AbstractReferenceCountedByteBuf {
25
26 private final Recycler.Handle recyclerHandle;
27
28 protected PoolChunk<T> chunk;
29 protected long handle;
30 protected T memory;
31 protected int offset;
32 protected int length;
33 int maxLength;
34 PoolThreadCache cache;
35 private ByteBuffer tmpNioBuf;
36 private ByteBufAllocator allocator;
37
38 protected PooledByteBuf(Recycler.Handle recyclerHandle, int maxCapacity) {
39 super(maxCapacity);
40 this.recyclerHandle = recyclerHandle;
41 }
42
43 void init(PoolChunk<T> chunk, long handle, int offset, int length, int maxLength, PoolThreadCache cache) {
44 init0(chunk, handle, offset, length, maxLength, cache);
45 }
46
47 void initUnpooled(PoolChunk<T> chunk, int length) {
48 init0(chunk, 0, chunk.offset, length, length, null);
49 }
50
51 private void init0(PoolChunk<T> chunk, long handle, int offset, int length, int maxLength, PoolThreadCache cache) {
52 assert handle >= 0;
53 assert chunk != null;
54
55 this.chunk = chunk;
56 memory = chunk.memory;
57 allocator = chunk.arena.parent;
58 this.cache = cache;
59 this.handle = handle;
60 this.offset = offset;
61 this.length = length;
62 this.maxLength = maxLength;
63 tmpNioBuf = null;
64 }
65
66
67
68
69 final void reuse(int maxCapacity) {
70 maxCapacity(maxCapacity);
71 setRefCnt(1);
72 setIndex0(0, 0);
73 discardMarks();
74 }
75
76 @Override
77 public final int capacity() {
78 return length;
79 }
80
81 @Override
82 public final ByteBuf capacity(int newCapacity) {
83 checkNewCapacity(newCapacity);
84
85
86 if (chunk.unpooled) {
87 if (newCapacity == length) {
88 return this;
89 }
90 } else {
91 if (newCapacity > length) {
92 if (newCapacity <= maxLength) {
93 length = newCapacity;
94 return this;
95 }
96 } else if (newCapacity < length) {
97 if (newCapacity > maxLength >>> 1) {
98 if (maxLength <= 512) {
99 if (newCapacity > maxLength - 16) {
100 length = newCapacity;
101 setIndex(Math.min(readerIndex(), newCapacity), Math.min(writerIndex(), newCapacity));
102 return this;
103 }
104 } else {
105 length = newCapacity;
106 setIndex(Math.min(readerIndex(), newCapacity), Math.min(writerIndex(), newCapacity));
107 return this;
108 }
109 }
110 } else {
111 return this;
112 }
113 }
114
115
116 chunk.arena.reallocate(this, newCapacity, true);
117 return this;
118 }
119
120 @Override
121 public final ByteBufAllocator alloc() {
122 return allocator;
123 }
124
125 @Override
126 public final ByteOrder order() {
127 return ByteOrder.BIG_ENDIAN;
128 }
129
130 @Override
131 public final ByteBuf unwrap() {
132 return null;
133 }
134
135 protected final ByteBuffer internalNioBuffer() {
136 ByteBuffer tmpNioBuf = this.tmpNioBuf;
137 if (tmpNioBuf == null) {
138 this.tmpNioBuf = tmpNioBuf = newInternalNioBuffer(memory);
139 }
140 return tmpNioBuf;
141 }
142
143 protected abstract ByteBuffer newInternalNioBuffer(T memory);
144
145 @Override
146 protected final void deallocate() {
147 if (handle >= 0) {
148 final long handle = this.handle;
149 this.handle = -1;
150 memory = null;
151 tmpNioBuf = null;
152 chunk.arena.free(chunk, handle, maxLength, cache);
153 chunk = null;
154 recycle();
155 }
156 }
157
158 private void recycle() {
159 Recycler.Handle recyclerHandle = this.recyclerHandle;
160 if (recyclerHandle != null) {
161 ((Recycler<Object>) recycler()).recycle(this, recyclerHandle);
162 }
163 }
164
165 protected abstract Recycler<?> recycler();
166
167 protected final int idx(int index) {
168 return offset + index;
169 }
170 }