Home / Class/ FixedChannelPoolMapDeadlockTest Class — netty Architecture

FixedChannelPoolMapDeadlockTest Class — netty Architecture

Architecture documentation for the FixedChannelPoolMapDeadlockTest class in FixedChannelPoolMapDeadlockTest.java from the netty codebase.

Entity Profile

Dependency Diagram

graph TD
  936e1d02_0c7d_5eb4_5c95_f3c3602bf9bc["FixedChannelPoolMapDeadlockTest"]
  f6cf26f4_0dbd_31fb_9f0b_9da73a27236a["FixedChannelPoolMapDeadlockTest.java"]
  936e1d02_0c7d_5eb4_5c95_f3c3602bf9bc -->|defined in| f6cf26f4_0dbd_31fb_9f0b_9da73a27236a
  45d501e3_9a27_4cb4_00da_f676cddbabe5["testDeadlockOnAcquire()"]
  936e1d02_0c7d_5eb4_5c95_f3c3602bf9bc -->|method| 45d501e3_9a27_4cb4_00da_f676cddbabe5
  10e63c8e_806e_9941_8260_15f8ee304e73["testDeadlockOnRemove()"]
  936e1d02_0c7d_5eb4_5c95_f3c3602bf9bc -->|method| 10e63c8e_806e_9941_8260_15f8ee304e73
  986a7a39_d83c_2d42_3095_18726001540d["await()"]
  936e1d02_0c7d_5eb4_5c95_f3c3602bf9bc -->|method| 986a7a39_d83c_2d42_3095_18726001540d
  ec1d1d7e_3f2c_8b44_83e4_1cb7783a3206["shutdown()"]
  936e1d02_0c7d_5eb4_5c95_f3c3602bf9bc -->|method| ec1d1d7e_3f2c_8b44_83e4_1cb7783a3206

Relationship Graph

Source Code

transport/src/test/java/io/netty/channel/pool/FixedChannelPoolMapDeadlockTest.java lines 38–264

public class FixedChannelPoolMapDeadlockTest {

    private static final NoopHandler NOOP_HANDLER = new NoopHandler();

    @Test
    public void testDeadlockOnAcquire() throws Exception {

        final EventLoop threadA1 = new DefaultEventLoop();
        final Bootstrap bootstrapA1 = new Bootstrap()
                .channel(LocalChannel.class).group(threadA1).localAddress(new LocalAddress("A1"));
        final EventLoop threadA2 = new DefaultEventLoop();
        final Bootstrap bootstrapA2 = new Bootstrap()
                .channel(LocalChannel.class).group(threadA2).localAddress(new LocalAddress("A2"));
        final EventLoop threadB1 = new DefaultEventLoop();
        final Bootstrap bootstrapB1 = new Bootstrap()
                .channel(LocalChannel.class).group(threadB1).localAddress(new LocalAddress("B1"));
        final EventLoop threadB2 = new DefaultEventLoop();
        final Bootstrap bootstrapB2 = new Bootstrap()
                .channel(LocalChannel.class).group(threadB2).localAddress(new LocalAddress("B2"));

        final FixedChannelPool poolA1 = new FixedChannelPool(bootstrapA1, NOOP_HANDLER, 1);
        final FixedChannelPool poolA2 = new FixedChannelPool(bootstrapB2, NOOP_HANDLER, 1);
        final FixedChannelPool poolB1 = new FixedChannelPool(bootstrapB1, NOOP_HANDLER, 1);
        final FixedChannelPool poolB2 = new FixedChannelPool(bootstrapA2, NOOP_HANDLER, 1);

        // Synchronize threads on these barriers to ensure order of execution, first wait until each thread is inside
        // the newPool callback, then hold the two threads that should lose the match until the first two returns, then
        // release them to test if they deadlock when trying to release their pools on each other's threads.
        final CyclicBarrier arrivalBarrier = new CyclicBarrier(4);
        final CyclicBarrier releaseBarrier = new CyclicBarrier(3);

        final AbstractChannelPoolMap<String, FixedChannelPool> channelPoolMap =
                new AbstractChannelPoolMap<String, FixedChannelPool>() {

            @Override
            protected FixedChannelPool newPool(String key) {

                // Thread A1 gets a new pool on eventexecutor thread A1 (anywhere but A2 or B2)
                // Thread B1 gets a new pool on eventexecutor thread B1 (anywhere but A2 or B2)
                // Thread A2 gets a new pool on eventexecutor thread B2
                // Thread B2 gets a new pool on eventexecutor thread A2

                if ("A".equals(key)) {
                    if (threadA1.inEventLoop()) {
                        // Thread A1 gets pool A with thread A1
                        await(arrivalBarrier);
                        return poolA1;
                    } else if (threadA2.inEventLoop()) {
                        // Thread A2 gets pool A with thread B2, but only after A1 won
                        await(arrivalBarrier);
                        await(releaseBarrier);
                        return poolA2;
                    }
                } else if ("B".equals(key)) {
                    if (threadB1.inEventLoop()) {
                        // Thread B1 gets pool with thread B1
                        await(arrivalBarrier);
                        return poolB1;
                    } else if (threadB2.inEventLoop()) {
                        // Thread B2 gets pool with thread A2
                        await(arrivalBarrier);
                        await(releaseBarrier);
                        return poolB2;
                    }
                }
                throw new AssertionError("Unexpected key=" + key + " or thread="
                                         + Thread.currentThread().getName());
            }
        };

        // Thread A1 calls ChannelPoolMap.get(A)
        // Thread A2 calls ChannelPoolMap.get(A)
        // Thread B1 calls ChannelPoolMap.get(B)
        // Thread B2 calls ChannelPoolMap.get(B)

        Future<FixedChannelPool> futureA1 = threadA1.submit(new Callable<FixedChannelPool>() {
            @Override
            public FixedChannelPool call() throws Exception {
                return channelPoolMap.get("A");
            }
        });

Frequently Asked Questions

What is the FixedChannelPoolMapDeadlockTest class?
FixedChannelPoolMapDeadlockTest is a class in the netty codebase, defined in transport/src/test/java/io/netty/channel/pool/FixedChannelPoolMapDeadlockTest.java.
Where is FixedChannelPoolMapDeadlockTest defined?
FixedChannelPoolMapDeadlockTest is defined in transport/src/test/java/io/netty/channel/pool/FixedChannelPoolMapDeadlockTest.java at line 38.

Analyze Your Own Codebase

Get architecture documentation, dependency graphs, and domain analysis for your codebase in minutes.

Try Supermodel Free