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
}
}
}
}
}
Source
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