|
28 | 28 | import io.netty.util.AbstractReferenceCounted;
|
29 | 29 | import io.netty.util.ReferenceCountUtil;
|
30 | 30 | import io.netty.util.ReferenceCounted;
|
| 31 | +import io.netty.util.concurrent.AbstractEventExecutor; |
| 32 | +import io.netty.util.concurrent.EventExecutorGroup; |
| 33 | +import io.netty.util.concurrent.Future; |
31 | 34 | import org.junit.After;
|
32 | 35 | import org.junit.AfterClass;
|
33 | 36 | import org.junit.Test;
|
|
38 | 41 | import java.util.List;
|
39 | 42 | import java.util.Queue;
|
40 | 43 | import java.util.concurrent.CountDownLatch;
|
| 44 | +import java.util.concurrent.ExecutorService; |
| 45 | +import java.util.concurrent.Executors; |
41 | 46 | import java.util.concurrent.TimeUnit;
|
42 | 47 | import java.util.concurrent.atomic.AtomicReference;
|
43 | 48 |
|
@@ -572,6 +577,37 @@ public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws E
|
572 | 577 | assertSame(exception, error.get());
|
573 | 578 | }
|
574 | 579 |
|
| 580 | + @Test |
| 581 | + public void testChannelUnregistrationWithCustomExecutor() throws Exception { |
| 582 | + final CountDownLatch channelLatch = new CountDownLatch(1); |
| 583 | + final CountDownLatch handlerLatch = new CountDownLatch(1); |
| 584 | + ChannelPipeline pipeline = new LocalChannel().pipeline(); |
| 585 | + pipeline.addLast(new ChannelInitializer<Channel>() { |
| 586 | + @Override |
| 587 | + protected void initChannel(Channel ch) throws Exception { |
| 588 | + ch.pipeline().addLast(new WrapperExecutor(), |
| 589 | + new ChannelInboundHandlerAdapter() { |
| 590 | + |
| 591 | + @Override |
| 592 | + public void channelUnregistered(ChannelHandlerContext ctx) throws Exception { |
| 593 | + channelLatch.countDown(); |
| 594 | + } |
| 595 | + |
| 596 | + @Override |
| 597 | + public void handlerRemoved(ChannelHandlerContext ctx) throws Exception { |
| 598 | + handlerLatch.countDown(); |
| 599 | + } |
| 600 | + }); |
| 601 | + } |
| 602 | + }); |
| 603 | + Channel channel = pipeline.channel(); |
| 604 | + group.register(channel); |
| 605 | + channel.close(); |
| 606 | + channel.deregister(); |
| 607 | + assertTrue(channelLatch.await(2, TimeUnit.SECONDS)); |
| 608 | + assertTrue(handlerLatch.await(2, TimeUnit.SECONDS)); |
| 609 | + } |
| 610 | + |
575 | 611 | private static int next(AbstractChannelHandlerContext ctx) {
|
576 | 612 | AbstractChannelHandlerContext next = ctx.next;
|
577 | 613 | if (next == null) {
|
@@ -683,4 +719,64 @@ public void handlerRemoved(ChannelHandlerContext ctx) {
|
683 | 719 | afterRemove = true;
|
684 | 720 | }
|
685 | 721 | }
|
| 722 | + |
| 723 | + private static final class WrapperExecutor extends AbstractEventExecutor { |
| 724 | + |
| 725 | + private final ExecutorService wrapped = Executors.newSingleThreadExecutor(); |
| 726 | + |
| 727 | + @Override |
| 728 | + public boolean isShuttingDown() { |
| 729 | + return wrapped.isShutdown(); |
| 730 | + } |
| 731 | + |
| 732 | + @Override |
| 733 | + public Future<?> shutdownGracefully(long l, long l2, TimeUnit timeUnit) { |
| 734 | + throw new IllegalStateException(); |
| 735 | + } |
| 736 | + |
| 737 | + @Override |
| 738 | + public Future<?> terminationFuture() { |
| 739 | + throw new IllegalStateException(); |
| 740 | + } |
| 741 | + |
| 742 | + @Override |
| 743 | + public void shutdown() { |
| 744 | + wrapped.shutdown(); |
| 745 | + } |
| 746 | + |
| 747 | + @Override |
| 748 | + public List<Runnable> shutdownNow() { |
| 749 | + return wrapped.shutdownNow(); |
| 750 | + } |
| 751 | + |
| 752 | + @Override |
| 753 | + public boolean isShutdown() { |
| 754 | + return wrapped.isShutdown(); |
| 755 | + } |
| 756 | + |
| 757 | + @Override |
| 758 | + public boolean isTerminated() { |
| 759 | + return wrapped.isTerminated(); |
| 760 | + } |
| 761 | + |
| 762 | + @Override |
| 763 | + public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException { |
| 764 | + return wrapped.awaitTermination(timeout, unit); |
| 765 | + } |
| 766 | + |
| 767 | + @Override |
| 768 | + public EventExecutorGroup parent() { |
| 769 | + return null; |
| 770 | + } |
| 771 | + |
| 772 | + @Override |
| 773 | + public boolean inEventLoop(Thread thread) { |
| 774 | + return false; |
| 775 | + } |
| 776 | + |
| 777 | + @Override |
| 778 | + public void execute(Runnable command) { |
| 779 | + wrapped.execute(command); |
| 780 | + } |
| 781 | + } |
686 | 782 | }
|
0 commit comments