Repository: netty/netty
File: transport/src/main/java/io/netty/channel/ManualIoEventLoop.java (Java)

Code before:
            if (setCurrentExecutor) {
                ThreadExecutorMap.setCurrentExecutor(old);
            }
        }
    }

    private int run(IoHandlerContext context, long runAllTasksTimeoutNanos) {
        if (!initialized) {
            if (owningThread.get() == null) {
                throw new IllegalStateException("Owning thread not set");
            }
            initialized = true;
            handler.initialize();
        }
        EventExecutor old = ThreadExecutorMap.setCurrentExecutor(this);
        try {
            if (isShuttingDown()) {
                if (terminationFuture.isDone()) {
                    // Already completely terminated
                    return 0;
                }
                return runAllTasksBeforeDestroy();
            }
            int run = handler.run(context);
            // Now run all tasks.
            return run + runAllTasks(runAllTasksTimeoutNanos, false);
        } finally {
            ThreadExecutorMap.setCurrentExecutor(old);
        }
    }

    private int runAllTasksBeforeDestroy() {
        // Run all tasks before prepare to destroy.
        int run = runAllTasks(-1, false);
        handler.prepareToDestroy();
        if (confirmShutdown()) {
            // Destroy the handler now and run all remaining tasks.
            try {
                handler.destroy();
                for (;;) {
                    int r = runAllTasks(-1, false);
                    run += r;
                    if (r == 0) {
                        break;
                    }
                }
            } finally {
                state.set(ST_TERMINATED);
                terminationFuture.setSuccess(null);
            }
        }

Review comment (suggestion):
i think there should be a way to skip runAllTasks here, maybe with a special value for runAllTasksTimeoutNanos

Code after:
            handler.initialize();
        }
        EventExecutor old = ThreadExecutorMap.setCurrentExecutor(this);
        try {
            if (isShuttingDown()) {
                if (terminationFuture.isDone()) {
                    // Already completely terminated
                    return 0;
                }
                return runAllTasksBeforeDestroy();
            }
            final int ioTasks = handler.run(context);
            // Now run all tasks.
            if (runAllTasksTimeoutNanos < 0) {
                return ioTasks;
            }
            assert runAllTasksTimeoutNanos >= 0;
            return ioTasks + runAllTasks(runAllTasksTimeoutNanos, false);
        } finally {
            ThreadExecutorMap.setCurrentExecutor(old);
        }
    }

    private int runAllTasksBeforeDestroy() {
        // Run all tasks before prepare to destroy.
        int run = runAllTasks(-1, false);
        handler.prepareToDestroy();
        if (confirmShutdown()) {
            // Destroy the handler now and run all remaining tasks.
            try {
                handler.destroy();
                for (;;) {
                    int r = runAllTasks(-1, false);
                    run += r;
                    if (r == 0) {
                        break;
                    }
                }
            } finally {
                state.set(ST_TERMINATED);
                terminationFuture.setSuccess(null);
            }
        }
        return run;
    }

    /**
     * Executes all ready IO and tasks for this {@link IoEventLoop}.
     * This methods will <strong>NOT</strong> block and wait for IO / tasks to be ready, it will just
     * return directly if there is nothing to do.
     * <p>