1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package io.netty.buffer;
18
19 import static io.netty.util.internal.ObjectUtil.checkPositiveOrZero;
20
21 import io.netty.util.ResourceLeakDetector;
22 import io.netty.util.ResourceLeakTracker;
23 import io.netty.util.internal.MathUtil;
24 import io.netty.util.internal.PlatformDependent;
25 import io.netty.util.internal.StringUtil;
26
27
28
29
30 public abstract class AbstractByteBufAllocator implements ByteBufAllocator {
31 static final int DEFAULT_INITIAL_CAPACITY = 256;
32 static final int DEFAULT_MAX_CAPACITY = Integer.MAX_VALUE;
33 static final int DEFAULT_MAX_COMPONENTS = 16;
34 static final int CALCULATE_THRESHOLD = 1048576 * 4;
35
36 static {
37 ResourceLeakDetector.addExclusions(AbstractByteBufAllocator.class, "toLeakAwareBuffer");
38 }
39
40 protected static ByteBuf toLeakAwareBuffer(ByteBuf buf) {
41 ResourceLeakTracker<ByteBuf> leak = AbstractByteBuf.leakDetector.track(buf);
42 if (leak != null) {
43 if (AbstractByteBuf.leakDetector.isRecordEnabled()) {
44 buf = new AdvancedLeakAwareByteBuf(buf, leak);
45 } else {
46 buf = new SimpleLeakAwareByteBuf(buf, leak);
47 }
48 }
49 return buf;
50 }
51
52 protected static CompositeByteBuf toLeakAwareBuffer(CompositeByteBuf buf) {
53 ResourceLeakTracker<ByteBuf> leak = AbstractByteBuf.leakDetector.track(buf);
54 if (leak != null) {
55 if (AbstractByteBuf.leakDetector.isRecordEnabled()) {
56 buf = new AdvancedLeakAwareCompositeByteBuf(buf, leak);
57 } else {
58 buf = new SimpleLeakAwareCompositeByteBuf(buf, leak);
59 }
60 }
61 return buf;
62 }
63
64 private final boolean directByDefault;
65 private final ByteBuf emptyBuf;
66
67
68
69
70 protected AbstractByteBufAllocator() {
71 this(false);
72 }
73
74
75
76
77
78
79
80 protected AbstractByteBufAllocator(boolean preferDirect) {
81 directByDefault = preferDirect && PlatformDependent.canReliabilyFreeDirectBuffers();
82 emptyBuf = new EmptyByteBuf(this);
83 }
84
85 @Override
86 public ByteBuf buffer() {
87 if (directByDefault) {
88 return directBuffer();
89 }
90 return heapBuffer();
91 }
92
93 @Override
94 public ByteBuf buffer(int initialCapacity) {
95 if (directByDefault) {
96 return directBuffer(initialCapacity);
97 }
98 return heapBuffer(initialCapacity);
99 }
100
101 @Override
102 public ByteBuf buffer(int initialCapacity, int maxCapacity) {
103 if (directByDefault) {
104 return directBuffer(initialCapacity, maxCapacity);
105 }
106 return heapBuffer(initialCapacity, maxCapacity);
107 }
108
109 @Override
110 public ByteBuf ioBuffer() {
111 if (PlatformDependent.canReliabilyFreeDirectBuffers() || isDirectBufferPooled()) {
112 return directBuffer(DEFAULT_INITIAL_CAPACITY);
113 }
114 return heapBuffer(DEFAULT_INITIAL_CAPACITY);
115 }
116
117 @Override
118 public ByteBuf ioBuffer(int initialCapacity) {
119 if (PlatformDependent.canReliabilyFreeDirectBuffers() || isDirectBufferPooled()) {
120 return directBuffer(initialCapacity);
121 }
122 return heapBuffer(initialCapacity);
123 }
124
125 @Override
126 public ByteBuf ioBuffer(int initialCapacity, int maxCapacity) {
127 if (PlatformDependent.canReliabilyFreeDirectBuffers() || isDirectBufferPooled()) {
128 return directBuffer(initialCapacity, maxCapacity);
129 }
130 return heapBuffer(initialCapacity, maxCapacity);
131 }
132
133 @Override
134 public ByteBuf heapBuffer() {
135 return heapBuffer(DEFAULT_INITIAL_CAPACITY, DEFAULT_MAX_CAPACITY);
136 }
137
138 @Override
139 public ByteBuf heapBuffer(int initialCapacity) {
140 return heapBuffer(initialCapacity, DEFAULT_MAX_CAPACITY);
141 }
142
143 @Override
144 public ByteBuf heapBuffer(int initialCapacity, int maxCapacity) {
145 if (initialCapacity == 0 && maxCapacity == 0) {
146 return emptyBuf;
147 }
148 validate(initialCapacity, maxCapacity);
149 return newHeapBuffer(initialCapacity, maxCapacity);
150 }
151
152 @Override
153 public ByteBuf directBuffer() {
154 return directBuffer(DEFAULT_INITIAL_CAPACITY, DEFAULT_MAX_CAPACITY);
155 }
156
157 @Override
158 public ByteBuf directBuffer(int initialCapacity) {
159 return directBuffer(initialCapacity, DEFAULT_MAX_CAPACITY);
160 }
161
162 @Override
163 public ByteBuf directBuffer(int initialCapacity, int maxCapacity) {
164 if (initialCapacity == 0 && maxCapacity == 0) {
165 return emptyBuf;
166 }
167 validate(initialCapacity, maxCapacity);
168 return newDirectBuffer(initialCapacity, maxCapacity);
169 }
170
171 @Override
172 public CompositeByteBuf compositeBuffer() {
173 if (directByDefault) {
174 return compositeDirectBuffer();
175 }
176 return compositeHeapBuffer();
177 }
178
179 @Override
180 public CompositeByteBuf compositeBuffer(int maxNumComponents) {
181 if (directByDefault) {
182 return compositeDirectBuffer(maxNumComponents);
183 }
184 return compositeHeapBuffer(maxNumComponents);
185 }
186
187 @Override
188 public CompositeByteBuf compositeHeapBuffer() {
189 return compositeHeapBuffer(DEFAULT_MAX_COMPONENTS);
190 }
191
192 @Override
193 public CompositeByteBuf compositeHeapBuffer(int maxNumComponents) {
194 return toLeakAwareBuffer(new CompositeByteBuf(this, false, maxNumComponents));
195 }
196
197 @Override
198 public CompositeByteBuf compositeDirectBuffer() {
199 return compositeDirectBuffer(DEFAULT_MAX_COMPONENTS);
200 }
201
202 @Override
203 public CompositeByteBuf compositeDirectBuffer(int maxNumComponents) {
204 return toLeakAwareBuffer(new CompositeByteBuf(this, true, maxNumComponents));
205 }
206
207 private static void validate(int initialCapacity, int maxCapacity) {
208 checkPositiveOrZero(initialCapacity, "initialCapacity");
209 if (initialCapacity > maxCapacity) {
210 throw new IllegalArgumentException(String.format(
211 "initialCapacity: %d (expected: not greater than maxCapacity(%d)",
212 initialCapacity, maxCapacity));
213 }
214 }
215
216
217
218
219 protected abstract ByteBuf newHeapBuffer(int initialCapacity, int maxCapacity);
220
221
222
223
224 protected abstract ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity);
225
226 @Override
227 public String toString() {
228 return StringUtil.simpleClassName(this) + "(directByDefault: " + directByDefault + ')';
229 }
230
231 @Override
232 public int calculateNewCapacity(int minNewCapacity, int maxCapacity) {
233 checkPositiveOrZero(minNewCapacity, "minNewCapacity");
234 if (minNewCapacity > maxCapacity) {
235 throw new IllegalArgumentException(String.format(
236 "minNewCapacity: %d (expected: not greater than maxCapacity(%d)",
237 minNewCapacity, maxCapacity));
238 }
239 final int threshold = CALCULATE_THRESHOLD;
240
241 if (minNewCapacity == threshold) {
242 return threshold;
243 }
244
245
246 if (minNewCapacity > threshold) {
247 int newCapacity = minNewCapacity / threshold * threshold;
248 if (newCapacity > maxCapacity - threshold) {
249 newCapacity = maxCapacity;
250 } else {
251 newCapacity += threshold;
252 }
253 return newCapacity;
254 }
255
256
257 final int newCapacity = MathUtil.findNextPositivePowerOfTwo(Math.max(minNewCapacity, 64));
258 return Math.min(newCapacity, maxCapacity);
259 }
260 }