@@ -31,16 +31,23 @@ final class CompositeBuffer extends RcSupport<Buffer, CompositeBuffer> implement
31
31
* non-composite copy of the buffer.
32
32
*/
33
33
private static final int MAX_CAPACITY = Integer .MAX_VALUE - 8 ;
34
- private static final Drop <CompositeBuffer > COMPOSITE_DROP = buf -> {
35
- for (Buffer b : buf .bufs ) {
36
- b .close ();
34
+ private static final Drop <CompositeBuffer > COMPOSITE_DROP = new Drop <CompositeBuffer >() {
35
+ @ Override
36
+ public void drop (CompositeBuffer buf ) {
37
+ for (Buffer b : buf .bufs ) {
38
+ b .close ();
39
+ }
40
+ buf .makeInaccessible ();
41
+ }
42
+
43
+ @ Override
44
+ public String toString () {
45
+ return "COMPOSITE_DROP" ;
37
46
}
38
- buf .makeInaccessible ();
39
47
};
40
48
41
49
private final BufferAllocator allocator ;
42
50
private final TornBufferAccessors tornBufAccessors ;
43
- private final boolean isSendable ;
44
51
private Buffer [] bufs ;
45
52
private int [] offsets ; // The offset, for the composite buffer, where each constituent buffer starts.
46
53
private int capacity ;
@@ -52,7 +59,7 @@ final class CompositeBuffer extends RcSupport<Buffer, CompositeBuffer> implement
52
59
private boolean readOnly ;
53
60
54
61
CompositeBuffer (BufferAllocator allocator , Deref <Buffer >[] refs ) {
55
- this (allocator , true , filterExternalBufs (refs ), COMPOSITE_DROP , false );
62
+ this (allocator , filterExternalBufs (refs ), COMPOSITE_DROP , false );
56
63
}
57
64
58
65
private static Buffer [] filterExternalBufs (Deref <Buffer >[] refs ) {
@@ -106,11 +113,10 @@ private static Stream<Buffer> flattenBuffer(Buffer buf) {
106
113
return Stream .of (buf );
107
114
}
108
115
109
- private CompositeBuffer (BufferAllocator allocator , boolean isSendable , Buffer [] bufs , Drop <CompositeBuffer > drop ,
116
+ private CompositeBuffer (BufferAllocator allocator , Buffer [] bufs , Drop <CompositeBuffer > drop ,
110
117
boolean acquireBufs ) {
111
118
super (drop );
112
119
this .allocator = allocator ;
113
- this .isSendable = isSendable ;
114
120
if (acquireBufs ) {
115
121
for (Buffer buf : bufs ) {
116
122
buf .acquire ();
@@ -297,46 +303,31 @@ public Buffer slice(int offset, int length) {
297
303
offset + ", and length was " + length + '.' );
298
304
}
299
305
Buffer choice = (Buffer ) chooseBuffer (offset , 0 );
300
- Buffer [] slices = null ;
301
- acquire (); // Increase reference count of the original composite buffer.
302
- Drop <CompositeBuffer > drop = obj -> {
303
- close (); // Decrement the reference count of the original composite buffer.
304
- COMPOSITE_DROP .drop (obj );
305
- };
306
-
307
- try {
308
- if (length > 0 ) {
309
- slices = new Buffer [bufs .length ];
310
- int off = subOffset ;
311
- int cap = length ;
312
- int i ;
313
- for (i = searchOffsets (offset ); cap > 0 ; i ++) {
314
- var buf = bufs [i ];
315
- int avail = buf .capacity () - off ;
316
- slices [i ] = buf .slice (off , Math .min (cap , avail ));
317
- cap -= avail ;
318
- off = 0 ;
319
- }
320
- slices = Arrays .copyOf (slices , i );
321
- } else {
322
- // Specialize for length == 0, since we must slice from at least one constituent buffer.
323
- slices = new Buffer [] { choice .slice (subOffset , 0 ) };
324
- }
325
-
326
- return new CompositeBuffer (allocator , false , slices , drop , true );
327
- } catch (Throwable throwable ) {
328
- // We called acquire prior to the try-clause. We need to undo that if we're not creating a composite buffer:
329
- close ();
330
- throw throwable ;
331
- } finally {
332
- if (slices != null ) {
333
- for (Buffer slice : slices ) {
334
- if (slice != null ) {
335
- slice .close (); // Ownership now transfers to the composite buffer.
336
- }
337
- }
338
- }
306
+ Buffer [] slices ;
307
+
308
+ if (length > 0 ) {
309
+ slices = new Buffer [bufs .length ];
310
+ int off = subOffset ;
311
+ int cap = length ;
312
+ int i ;
313
+ for (i = searchOffsets (offset ); cap > 0 ; i ++) {
314
+ var buf = bufs [i ];
315
+ int avail = buf .capacity () - off ;
316
+ slices [i ] = buf .slice (off , Math .min (cap , avail ));
317
+ cap -= avail ;
318
+ off = 0 ;
319
+ }
320
+ slices = Arrays .copyOf (slices , i );
321
+ } else {
322
+ // Specialize for length == 0, since we must slice from at least one constituent buffer.
323
+ slices = new Buffer [] { choice .slice (subOffset , 0 ) };
339
324
}
325
+
326
+ // Use the constructor that skips filtering out empty buffers, and skips acquiring on the buffers.
327
+ // This is important because 1) slice() already acquired the buffers, and 2) if this slice is empty
328
+ // then we need to keep holding on to it to prevent this originating composite buffer from getting
329
+ // ownership. If it did, its behaviour would be inconsistent with that of a non-composite buffer.
330
+ return new CompositeBuffer (allocator , slices , COMPOSITE_DROP , false );
340
331
}
341
332
342
333
@ Override
@@ -749,7 +740,7 @@ public Buffer bifurcate() {
749
740
}
750
741
if (bufs .length == 0 ) {
751
742
// Bifurcating a zero-length buffer is trivial.
752
- return new CompositeBuffer (allocator , true , bufs , unsafeGetDrop (), true ).order (order );
743
+ return new CompositeBuffer (allocator , bufs , unsafeGetDrop (), true ).order (order );
753
744
}
754
745
755
746
int i = searchOffsets (woff );
@@ -761,7 +752,7 @@ public Buffer bifurcate() {
761
752
}
762
753
computeBufferOffsets ();
763
754
try {
764
- var compositeBuf = new CompositeBuffer (allocator , true , bifs , unsafeGetDrop (), true );
755
+ var compositeBuf = new CompositeBuffer (allocator , bifs , unsafeGetDrop (), true );
765
756
compositeBuf .order = order ; // Preserve byte order even if bifs array is empty.
766
757
return compositeBuf ;
767
758
} finally {
@@ -1164,7 +1155,7 @@ public CompositeBuffer transferOwnership(Drop<CompositeBuffer> drop) {
1164
1155
for (int i = 0 ; i < sends .length ; i ++) {
1165
1156
received [i ] = sends [i ].receive ();
1166
1157
}
1167
- var composite = new CompositeBuffer (allocator , true , received , drop , true );
1158
+ var composite = new CompositeBuffer (allocator , received , drop , true );
1168
1159
composite .readOnly = readOnly ;
1169
1160
drop .attach (composite );
1170
1161
return composite ;
@@ -1179,18 +1170,9 @@ void makeInaccessible() {
1179
1170
closed = true ;
1180
1171
}
1181
1172
1182
- @ Override
1183
- protected IllegalStateException notSendableException () {
1184
- if (!isSendable ) {
1185
- return new IllegalStateException (
1186
- "Cannot send() this buffer. This buffer might be a slice of another buffer." );
1187
- }
1188
- return super .notSendableException ();
1189
- }
1190
-
1191
1173
@ Override
1192
1174
public boolean isOwned () {
1193
- return isSendable && super .isOwned () && allConstituentsAreOwned ();
1175
+ return super .isOwned () && allConstituentsAreOwned ();
1194
1176
}
1195
1177
1196
1178
private boolean allConstituentsAreOwned () {
0 commit comments