@@ -48,7 +48,6 @@ public String toString() {
4848
4949 private final BufferAllocator allocator ;
5050 private final TornBufferAccessors tornBufAccessors ;
51- private final boolean isSendable ;
5251 private Buffer [] bufs ;
5352 private int [] offsets ; // The offset, for the composite buffer, where each constituent buffer starts.
5453 private int capacity ;
@@ -60,7 +59,7 @@ public String toString() {
6059 private boolean readOnly ;
6160
6261 CompositeBuffer (BufferAllocator allocator , Deref <Buffer >[] refs ) {
63- this (allocator , true , filterExternalBufs (refs ), COMPOSITE_DROP , false );
62+ this (allocator , filterExternalBufs (refs ), COMPOSITE_DROP , false );
6463 }
6564
6665 private static Buffer [] filterExternalBufs (Deref <Buffer >[] refs ) {
@@ -114,11 +113,10 @@ private static Stream<Buffer> flattenBuffer(Buffer buf) {
114113 return Stream .of (buf );
115114 }
116115
117- private CompositeBuffer (BufferAllocator allocator , boolean isSendable , Buffer [] bufs , Drop <CompositeBuffer > drop ,
116+ private CompositeBuffer (BufferAllocator allocator , Buffer [] bufs , Drop <CompositeBuffer > drop ,
118117 boolean acquireBufs ) {
119118 super (drop );
120119 this .allocator = allocator ;
121- this .isSendable = isSendable ;
122120 if (acquireBufs ) {
123121 for (Buffer buf : bufs ) {
124122 buf .acquire ();
@@ -305,46 +303,31 @@ public Buffer slice(int offset, int length) {
305303 offset + ", and length was " + length + '.' );
306304 }
307305 Buffer choice = (Buffer ) chooseBuffer (offset , 0 );
308- Buffer [] slices = null ;
309- acquire (); // Increase reference count of the original composite buffer.
310- Drop <CompositeBuffer > drop = obj -> {
311- close (); // Decrement the reference count of the original composite buffer.
312- COMPOSITE_DROP .drop (obj );
313- };
314-
315- try {
316- if (length > 0 ) {
317- slices = new Buffer [bufs .length ];
318- int off = subOffset ;
319- int cap = length ;
320- int i ;
321- for (i = searchOffsets (offset ); cap > 0 ; i ++) {
322- var buf = bufs [i ];
323- int avail = buf .capacity () - off ;
324- slices [i ] = buf .slice (off , Math .min (cap , avail ));
325- cap -= avail ;
326- off = 0 ;
327- }
328- slices = Arrays .copyOf (slices , i );
329- } else {
330- // Specialize for length == 0, since we must slice from at least one constituent buffer.
331- slices = new Buffer [] { choice .slice (subOffset , 0 ) };
332- }
333-
334- return new CompositeBuffer (allocator , false , slices , drop , true );
335- } catch (Throwable throwable ) {
336- // We called acquire prior to the try-clause. We need to undo that if we're not creating a composite buffer:
337- close ();
338- throw throwable ;
339- } finally {
340- if (slices != null ) {
341- for (Buffer slice : slices ) {
342- if (slice != null ) {
343- slice .close (); // Ownership now transfers to the composite buffer.
344- }
345- }
346- }
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 ) };
347324 }
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 );
348331 }
349332
350333 @ Override
@@ -757,7 +740,7 @@ public Buffer bifurcate() {
757740 }
758741 if (bufs .length == 0 ) {
759742 // Bifurcating a zero-length buffer is trivial.
760- return new CompositeBuffer (allocator , true , bufs , unsafeGetDrop (), true ).order (order );
743+ return new CompositeBuffer (allocator , bufs , unsafeGetDrop (), true ).order (order );
761744 }
762745
763746 int i = searchOffsets (woff );
@@ -769,7 +752,7 @@ public Buffer bifurcate() {
769752 }
770753 computeBufferOffsets ();
771754 try {
772- var compositeBuf = new CompositeBuffer (allocator , true , bifs , unsafeGetDrop (), true );
755+ var compositeBuf = new CompositeBuffer (allocator , bifs , unsafeGetDrop (), true );
773756 compositeBuf .order = order ; // Preserve byte order even if bifs array is empty.
774757 return compositeBuf ;
775758 } finally {
@@ -1172,7 +1155,7 @@ public CompositeBuffer transferOwnership(Drop<CompositeBuffer> drop) {
11721155 for (int i = 0 ; i < sends .length ; i ++) {
11731156 received [i ] = sends [i ].receive ();
11741157 }
1175- var composite = new CompositeBuffer (allocator , true , received , drop , true );
1158+ var composite = new CompositeBuffer (allocator , received , drop , true );
11761159 composite .readOnly = readOnly ;
11771160 drop .attach (composite );
11781161 return composite ;
@@ -1187,18 +1170,9 @@ void makeInaccessible() {
11871170 closed = true ;
11881171 }
11891172
1190- @ Override
1191- protected IllegalStateException notSendableException () {
1192- if (!isSendable ) {
1193- return new IllegalStateException (
1194- "Cannot send() this buffer. This buffer might be a slice of another buffer." );
1195- }
1196- return super .notSendableException ();
1197- }
1198-
11991173 @ Override
12001174 public boolean isOwned () {
1201- return isSendable && super .isOwned () && allConstituentsAreOwned ();
1175+ return super .isOwned () && allConstituentsAreOwned ();
12021176 }
12031177
12041178 private boolean allConstituentsAreOwned () {
0 commit comments