private static void notifyListenerWithStackOverFlowProtection(final EventExecutor executor,
                                                                  final Future<?> future,
                                                                  final GenericFutureListener<?> listener) {
        if (executor.inEventLoop()) {
            final InternalThreadLocalMap threadLocals = InternalThreadLocalMap.get();
            final int stackDepth = threadLocals.futureListenerStackDepth();
            if (stackDepth < MAX_LISTENER_STACK_DEPTH) {
                threadLocals.setFutureListenerStackDepth(stackDepth + 1);
                try {
                    notifyListener0(future, listener);
                } finally {
                    threadLocals.setFutureListenerStackDepth(stackDepth);
                }
                return;
            }
        }

        safeExecute(executor, new Runnable() {
            @Override
            public void run() {
                notifyListener0(future, listener);
            }
        });
    }
private static void notifyListenerWithStackOverFlowProtection ( final EventExecutor executor , final Future < ? > future , final GenericFutureListener < ? > listener ) { if ( executor . inEventLoop ( ) ) { final InternalThreadLocalMap threadLocals = InternalThreadLocalMap . get ( ) ; final int stackDepth = threadLocals . futureListenerStackDepth ( ) ; if ( stackDepth < MAX_LISTENER_STACK_DEPTH ) { threadLocals . setFutureListenerStackDepth ( stackDepth + 1 ) ; try { notifyListener0 ( future , listener ) ; } finally { threadLocals . setFutureListenerStackDepth ( stackDepth ) ; } return ; } } safeExecute ( executor , new Runnable ( ) { @ Override public void run ( ) { notifyListener0 ( future , listener ) ; } } ) ; }
The logic in this method should be identical to {@link #notifyListeners()} but
cannot share code because the listener(s) cannot be cached for an instance of {@link DefaultPromise} since the
listener(s) may be changed and is protected by a synchronized operation.