Home / Class/ NonStickyOrderedEventExecutor Class — netty Architecture

NonStickyOrderedEventExecutor Class — netty Architecture

Architecture documentation for the NonStickyOrderedEventExecutor class in NonStickyEventExecutorGroup.java from the netty codebase.

Entity Profile

Dependency Diagram

graph TD
  0a6a7b0f_e4f7_262e_c01d_c793011590ee["NonStickyOrderedEventExecutor"]
  eafe5945_ac14_eb1d_92de_38d929817de3["NonStickyEventExecutorGroup.java"]
  0a6a7b0f_e4f7_262e_c01d_c793011590ee -->|defined in| eafe5945_ac14_eb1d_92de_38d929817de3
  cd034597_c288_2b46_c58f_c076fb561608["NonStickyOrderedEventExecutor()"]
  0a6a7b0f_e4f7_262e_c01d_c793011590ee -->|method| cd034597_c288_2b46_c58f_c076fb561608
  26597b68_1b9b_0daa_4db4_2de2cf123abc["run()"]
  0a6a7b0f_e4f7_262e_c01d_c793011590ee -->|method| 26597b68_1b9b_0daa_4db4_2de2cf123abc
  9bb0e378_4e4c_d4b9_0a03_d43ee31b1360["inEventLoop()"]
  0a6a7b0f_e4f7_262e_c01d_c793011590ee -->|method| 9bb0e378_4e4c_d4b9_0a03_d43ee31b1360
  b970b881_5012_4a5a_f638_117bd5bebca1["isShuttingDown()"]
  0a6a7b0f_e4f7_262e_c01d_c793011590ee -->|method| b970b881_5012_4a5a_f638_117bd5bebca1
  f6942c13_6767_70e4_9a2f_28ceb3532ddc["shutdownGracefully()"]
  0a6a7b0f_e4f7_262e_c01d_c793011590ee -->|method| f6942c13_6767_70e4_9a2f_28ceb3532ddc
  6fc39246_cf14_5372_d5f9_bf6310d61882["terminationFuture()"]
  0a6a7b0f_e4f7_262e_c01d_c793011590ee -->|method| 6fc39246_cf14_5372_d5f9_bf6310d61882
  acf72bb7_a04d_fba2_d0f6_17082caf74ec["shutdown()"]
  0a6a7b0f_e4f7_262e_c01d_c793011590ee -->|method| acf72bb7_a04d_fba2_d0f6_17082caf74ec
  78999c9b_78c3_151e_9482_02d236ac3d2a["isShutdown()"]
  0a6a7b0f_e4f7_262e_c01d_c793011590ee -->|method| 78999c9b_78c3_151e_9482_02d236ac3d2a
  a5143ff1_f60c_e97f_db3d_1a51e1317765["isTerminated()"]
  0a6a7b0f_e4f7_262e_c01d_c793011590ee -->|method| a5143ff1_f60c_e97f_db3d_1a51e1317765
  bfef11b1_72ba_27d4_984e_73e7d6906d84["awaitTermination()"]
  0a6a7b0f_e4f7_262e_c01d_c793011590ee -->|method| bfef11b1_72ba_27d4_984e_73e7d6906d84
  f324b658_e5d7_1d39_280a_67ba14086087["execute()"]
  0a6a7b0f_e4f7_262e_c01d_c793011590ee -->|method| f324b658_e5d7_1d39_280a_67ba14086087

Relationship Graph

Source Code

common/src/main/java/io/netty/util/concurrent/NonStickyEventExecutorGroup.java lines 215–347

    private static final class NonStickyOrderedEventExecutor extends AbstractEventExecutor
            implements Runnable, OrderedEventExecutor {
        private final EventExecutor executor;
        private final Queue<Runnable> tasks = PlatformDependent.newMpscQueue();

        private static final int NONE = 0;
        private static final int SUBMITTED = 1;
        private static final int RUNNING = 2;

        private final AtomicInteger state = new AtomicInteger();
        private final int maxTaskExecutePerRun;

        private final AtomicReference<Thread> executingThread = new AtomicReference<Thread>();

        NonStickyOrderedEventExecutor(EventExecutor executor, int maxTaskExecutePerRun) {
            super(executor);
            this.executor = executor;
            this.maxTaskExecutePerRun = maxTaskExecutePerRun;
        }

        @Override
        public void run() {
            if (!state.compareAndSet(SUBMITTED, RUNNING)) {
                return;
            }
            Thread current = Thread.currentThread();
            executingThread.set(current);
            for (;;) {
                int i = 0;
                try {
                    for (; i < maxTaskExecutePerRun; i++) {
                        Runnable task = tasks.poll();
                        if (task == null) {
                            break;
                        }
                        safeExecute(task);
                    }
                } finally {
                    if (i == maxTaskExecutePerRun) {
                        try {
                            state.set(SUBMITTED);
                            // Only set executingThread to null if no other thread did update it yet.
                            executingThread.compareAndSet(current, null);
                            executor.execute(this);
                            return; // done
                        } catch (Throwable ignore) {
                            // Restore executingThread since we're continuing to execute tasks.
                            executingThread.set(current);
                            // Reset the state back to running as we will keep on executing tasks.
                            state.set(RUNNING);
                            // if an error happened we should just ignore it and let the loop run again as there is not
                            // much else we can do. Most likely this was triggered by a full task queue. In this case
                            // we just will run more tasks and try again later.
                        }
                    } else {
                        state.set(NONE);
                        // After setting the state to NONE, look at the tasks queue one more time.
                        // If it is empty, then we can return from this method.
                        // Otherwise, it means the producer thread has called execute(Runnable)
                        // and enqueued a task in between the tasks.poll() above and the state.set(NONE) here.
                        // There are two possible scenarios when this happens
                        //
                        // 1. The producer thread sees state == NONE, hence the compareAndSet(NONE, SUBMITTED)
                        //    is successfully setting the state to SUBMITTED. This mean the producer
                        //    will call / has called executor.execute(this). In this case, we can just return.
                        // 2. The producer thread don't see the state change, hence the compareAndSet(NONE, SUBMITTED)
                        //    returns false. In this case, the producer thread won't call executor.execute.
                        //    In this case, we need to change the state to RUNNING and keeps running.
                        //
                        // The above cases can be distinguished by performing a
                        // compareAndSet(NONE, RUNNING). If it returns "false", it is case 1; otherwise it is case 2.
                        if (tasks.isEmpty() || !state.compareAndSet(NONE, RUNNING)) {
                            // Only set executingThread to null if no other thread did update it yet.
                            executingThread.compareAndSet(current, null);
                            return; // done
                        }
                    }
                }
            }
        }

Frequently Asked Questions

What is the NonStickyOrderedEventExecutor class?
NonStickyOrderedEventExecutor is a class in the netty codebase, defined in common/src/main/java/io/netty/util/concurrent/NonStickyEventExecutorGroup.java.
Where is NonStickyOrderedEventExecutor defined?
NonStickyOrderedEventExecutor is defined in common/src/main/java/io/netty/util/concurrent/NonStickyEventExecutorGroup.java at line 215.

Analyze Your Own Codebase

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

Try Supermodel Free