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;
42 switch (ResourceLeakDetector.getLevel()) {
43 case SIMPLE:
44 leak = AbstractByteBuf.leakDetector.track(buf);
45 if (leak != null) {
46 buf = new SimpleLeakAwareByteBuf(buf, leak);
47 }
48 break;
49 case ADVANCED:
50 case PARANOID:
51 leak = AbstractByteBuf.leakDetector.track(buf);
52 if (leak != null) {
53 buf = new AdvancedLeakAwareByteBuf(buf, leak);
54 }
55 break;
56 default:
57 break;
58 }
59 return buf;
60 }
61
62 protected static CompositeByteBuf toLeakAwareBuffer(CompositeByteBuf buf) {
63 ResourceLeakTracker<ByteBuf> leak;
64 switch (ResourceLeakDetector.getLevel()) {
65 case SIMPLE:
66 leak = AbstractByteBuf.leakDetector.track(buf);
67 if (leak != null) {
68 buf = new SimpleLeakAwareCompositeByteBuf(buf, leak);
69 }
70 break;
71 case ADVANCED:
72 case PARANOID:
73 leak = AbstractByteBuf.leakDetector.track(buf);
74 if (leak != null) {
75 buf = new AdvancedLeakAwareCompositeByteBuf(buf, leak);
76 }
77 break;
78 default:
79 break;
80 }
81 return buf;
82 }
83
84 private final boolean directByDefault;
85 private final ByteBuf emptyBuf;
86
87
88
89
90 protected AbstractByteBufAllocator() {
91 this(false);
92 }
93
94
95
96
97
98
99
100 protected AbstractByteBufAllocator(boolean preferDirect) {
101 directByDefault = preferDirect && PlatformDependent.hasUnsafe();
102 emptyBuf = new EmptyByteBuf(this);
103 }
104
105 @Override
106 public ByteBuf buffer() {
107 if (directByDefault) {
108 return directBuffer();
109 }
110 return heapBuffer();
111 }
112
113 @Override
114 public ByteBuf buffer(int initialCapacity) {
115 if (directByDefault) {
116 return directBuffer(initialCapacity);
117 }
118 return heapBuffer(initialCapacity);
119 }
120
121 @Override
122 public ByteBuf buffer(int initialCapacity, int maxCapacity) {
123 if (directByDefault) {
124 return directBuffer(initialCapacity, maxCapacity);
125 }
126 return heapBuffer(initialCapacity, maxCapacity);
127 }
128
129 @Override
130 public ByteBuf ioBuffer() {
131 if (PlatformDependent.hasUnsafe() || isDirectBufferPooled()) {
132 return directBuffer(DEFAULT_INITIAL_CAPACITY);
133 }
134 return heapBuffer(DEFAULT_INITIAL_CAPACITY);
135 }
136
137 @Override
138 public ByteBuf ioBuffer(int initialCapacity) {
139 if (PlatformDependent.hasUnsafe() || isDirectBufferPooled()) {
140 return directBuffer(initialCapacity);
141 }
142 return heapBuffer(initialCapacity);
143 }
144
145 @Override
146 public ByteBuf ioBuffer(int initialCapacity, int maxCapacity) {
147 if (PlatformDependent.hasUnsafe() || isDirectBufferPooled()) {
148 return directBuffer(initialCapacity, maxCapacity);
149 }
150 return heapBuffer(initialCapacity, maxCapacity);
151 }
152
153 @Override
154 public ByteBuf heapBuffer() {
155 return heapBuffer(DEFAULT_INITIAL_CAPACITY, DEFAULT_MAX_CAPACITY);
156 }
157
158 @Override
159 public ByteBuf heapBuffer(int initialCapacity) {
160 return heapBuffer(initialCapacity, DEFAULT_MAX_CAPACITY);
161 }
162
163 @Override
164 public ByteBuf heapBuffer(int initialCapacity, int maxCapacity) {
165 if (initialCapacity == 0 && maxCapacity == 0) {
166 return emptyBuf;
167 }
168 validate(initialCapacity, maxCapacity);
169 return newHeapBuffer(initialCapacity, maxCapacity);
170 }
171
172 @Override
173 public ByteBuf directBuffer() {
174 return directBuffer(DEFAULT_INITIAL_CAPACITY, DEFAULT_MAX_CAPACITY);
175 }
176
177 @Override
178 public ByteBuf directBuffer(int initialCapacity) {
179 return directBuffer(initialCapacity, DEFAULT_MAX_CAPACITY);
180 }
181
182 @Override
183 public ByteBuf directBuffer(int initialCapacity, int maxCapacity) {
184 if (initialCapacity == 0 && maxCapacity == 0) {
185 return emptyBuf;
186 }
187 validate(initialCapacity, maxCapacity);
188 return newDirectBuffer(initialCapacity, maxCapacity);
189 }
190
191 @Override
192 public CompositeByteBuf compositeBuffer() {
193 if (directByDefault) {
194 return compositeDirectBuffer();
195 }
196 return compositeHeapBuffer();
197 }
198
199 @Override
200 public CompositeByteBuf compositeBuffer(int maxNumComponents) {
201 if (directByDefault) {
202 return compositeDirectBuffer(maxNumComponents);
203 }
204 return compositeHeapBuffer(maxNumComponents);
205 }
206
207 @Override
208 public CompositeByteBuf compositeHeapBuffer() {
209 return compositeHeapBuffer(DEFAULT_MAX_COMPONENTS);
210 }
211
212 @Override
213 public CompositeByteBuf compositeHeapBuffer(int maxNumComponents) {
214 return toLeakAwareBuffer(new CompositeByteBuf(this, false, maxNumComponents));
215 }
216
217 @Override
218 public CompositeByteBuf compositeDirectBuffer() {
219 return compositeDirectBuffer(DEFAULT_MAX_COMPONENTS);
220 }
221
222 @Override
223 public CompositeByteBuf compositeDirectBuffer(int maxNumComponents) {
224 return toLeakAwareBuffer(new CompositeByteBuf(this, true, maxNumComponents));
225 }
226
227 private static void validate(int initialCapacity, int maxCapacity) {
228 checkPositiveOrZero(initialCapacity, "initialCapacity");
229 if (initialCapacity > maxCapacity) {
230 throw new IllegalArgumentException(String.format(
231 "initialCapacity: %d (expected: not greater than maxCapacity(%d)",
232 initialCapacity, maxCapacity));
233 }
234 }
235
236
237
238
239 protected abstract ByteBuf newHeapBuffer(int initialCapacity, int maxCapacity);
240
241
242
243
244 protected abstract ByteBuf newDirectBuffer(int initialCapacity, int maxCapacity);
245
246 @Override
247 public String toString() {
248 return StringUtil.simpleClassName(this) + "(directByDefault: " + directByDefault + ')';
249 }
250
251 @Override
252 public int calculateNewCapacity(int minNewCapacity, int maxCapacity) {
253 checkPositiveOrZero(minNewCapacity, "minNewCapacity");
254 if (minNewCapacity > maxCapacity) {
255 throw new IllegalArgumentException(String.format(
256 "minNewCapacity: %d (expected: not greater than maxCapacity(%d)",
257 minNewCapacity, maxCapacity));
258 }
259 final int threshold = CALCULATE_THRESHOLD;
260
261 if (minNewCapacity == threshold) {
262 return threshold;
263 }
264
265
266 if (minNewCapacity > threshold) {
267 int newCapacity = minNewCapacity / threshold * threshold;
268 if (newCapacity > maxCapacity - threshold) {
269 newCapacity = maxCapacity;
270 } else {
271 newCapacity += threshold;
272 }
273 return newCapacity;
274 }
275
276
277 final int newCapacity = MathUtil.findNextPositivePowerOfTwo(Math.max(minNewCapacity, 64));
278 return Math.min(newCapacity, maxCapacity);
279 }
280 }