|
25 | 25 |
|
26 | 26 | package sun.nio.ch;
|
27 | 27 |
|
| 28 | +import java.lang.invoke.MethodHandles; |
| 29 | +import java.lang.invoke.VarHandle; |
28 | 30 | import java.nio.channels.*;
|
29 | 31 | import java.nio.ByteBuffer;
|
30 | 32 | import java.nio.BufferOverflowException;
|
31 | 33 | import java.net.*;
|
32 | 34 | import java.util.concurrent.*;
|
33 | 35 | import java.io.IOException;
|
| 36 | +import jdk.internal.invoke.MhUtil; |
34 | 37 | import jdk.internal.misc.Unsafe;
|
35 | 38 | import sun.net.util.SocketExceptions;
|
36 | 39 |
|
@@ -367,10 +370,13 @@ <A> Future<Void> implConnect(SocketAddress remote,
|
367 | 370 | * result when the read completes.
|
368 | 371 | */
|
369 | 372 | private class ReadTask<V,A> implements Runnable, Iocp.ResultHandler {
|
| 373 | + private static final VarHandle RELEASED = MhUtil.findVarHandle(MethodHandles.lookup(), |
| 374 | + "released", boolean.class); |
370 | 375 | private final ByteBuffer[] bufs;
|
371 | 376 | private final int numBufs;
|
372 | 377 | private final boolean scatteringRead;
|
373 | 378 | private final PendingFuture<V,A> result;
|
| 379 | + private volatile boolean released; |
374 | 380 |
|
375 | 381 | // set by run method
|
376 | 382 | private ByteBuffer[] shadow;
|
@@ -461,12 +467,14 @@ void updateBuffers(int bytesRead) {
|
461 | 467 | }
|
462 | 468 |
|
463 | 469 | void releaseBuffers() {
|
464 |
| - for (int i=0; i<numBufs; i++) { |
465 |
| - if (!(bufs[i] instanceof DirectBuffer)) { |
466 |
| - Util.releaseTemporaryDirectBuffer(shadow[i]); |
| 470 | + if (RELEASED.compareAndSet(this, false, true)) { |
| 471 | + for (int i = 0; i < numBufs; i++) { |
| 472 | + if (!(bufs[i] instanceof DirectBuffer)) { |
| 473 | + Util.releaseTemporaryDirectBuffer(shadow[i]); |
| 474 | + } |
467 | 475 | }
|
| 476 | + IOUtil.releaseScopes(scopeHandleReleasers); |
468 | 477 | }
|
469 |
| - IOUtil.releaseScopes(scopeHandleReleasers); |
470 | 478 | }
|
471 | 479 |
|
472 | 480 | @Override
|
@@ -641,10 +649,13 @@ public void run() {
|
641 | 649 | * result when the write completes.
|
642 | 650 | */
|
643 | 651 | private class WriteTask<V,A> implements Runnable, Iocp.ResultHandler {
|
| 652 | + private static final VarHandle RELEASED = MhUtil.findVarHandle(MethodHandles.lookup(), |
| 653 | + "released", boolean.class); |
644 | 654 | private final ByteBuffer[] bufs;
|
645 | 655 | private final int numBufs;
|
646 | 656 | private final boolean gatheringWrite;
|
647 | 657 | private final PendingFuture<V,A> result;
|
| 658 | + private volatile boolean released; |
648 | 659 |
|
649 | 660 | // set by run method
|
650 | 661 | private ByteBuffer[] shadow;
|
@@ -728,12 +739,14 @@ void updateBuffers(int bytesWritten) {
|
728 | 739 | }
|
729 | 740 |
|
730 | 741 | void releaseBuffers() {
|
731 |
| - for (int i=0; i<numBufs; i++) { |
732 |
| - if (!(bufs[i] instanceof DirectBuffer)) { |
733 |
| - Util.releaseTemporaryDirectBuffer(shadow[i]); |
| 742 | + if (RELEASED.compareAndSet(this, false, true)) { |
| 743 | + for (int i = 0; i < numBufs; i++) { |
| 744 | + if (!(bufs[i] instanceof DirectBuffer)) { |
| 745 | + Util.releaseTemporaryDirectBuffer(shadow[i]); |
| 746 | + } |
734 | 747 | }
|
| 748 | + IOUtil.releaseScopes(scopeHandleReleasers); |
735 | 749 | }
|
736 |
| - IOUtil.releaseScopes(scopeHandleReleasers); |
737 | 750 | }
|
738 | 751 |
|
739 | 752 | @Override
|
|
0 commit comments