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