/*
 * Copyright 2012 The Netty Project
 *
 * The Netty Project licenses this file to you under the Apache License,
 * version 2.0 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations
 * under the License.
 */
package io.netty.channel.aio;

import io.netty.channel.Channel;
import io.netty.channel.EventLoop;

import java.nio.channels.CompletionHandler;

/**
 * Special {@link CompletionHandler} which makes sure that the callback methods gets executed in the {@link EventLoop}
 */
public abstract class AioCompletionHandler<V, A extends Channel> implements CompletionHandler<V, A> {

    /**
     * See {@link CompletionHandler#completed(Object, Object)}
     */
    protected abstract void completed0(V result, A channel);

    /**
     * Set {@link CompletionHandler#failed(Throwable, Object)}
     */
    protected abstract void failed0(Throwable exc, A channel);

    @Override
    public final void completed(final V result, final A channel) {
        EventLoop loop = channel.eventLoop();
        if (loop.inEventLoop()) {
            completed0(result, channel);
        } else {
            loop.execute(new Runnable() {
                @Override
                public void run() {
                    completed0(result, channel);
                }
            });
        }
    }

    @Override
    public final void failed(final Throwable exc, final A channel) {
        EventLoop loop = channel.eventLoop();
        if (loop.inEventLoop()) {
            failed0(exc, channel);
        } else {
            loop.execute(new Runnable() {
                @Override
                public void run() {
                    failed0(exc, channel);
                }
            });
        }
    }
}

@@ -1295,205 +1295,697 @@
     
-@Override%0A    public final void completed(final V result, final A channel) %7B%0A        EventLoop loop = channel.eventLoop();%0A        if (loop.inEventLoop()) %7B%0A            completed0(result, channel);
+private static final int MAX_STACK_DEPTH = 8;%0A    private static final ThreadLocal%3CInteger%3E STACK_DEPTH = new ThreadLocal%3CInteger%3E() %7B%0A        @Override%0A        protected Integer initialValue() %7B%0A            return 0;%0A        %7D%0A    %7D;%0A%0A    @Override%0A    public final void completed(final V result, final A channel) %7B%0A        EventLoop loop = channel.eventLoop();%0A        if (loop.inEventLoop()) %7B%0A            Integer d = STACK_DEPTH.get();%0A            if (d %3C MAX_STACK_DEPTH) %7B%0A                STACK_DEPTH.set(d + 1);%0A                try %7B%0A                    completed0(result, channel);%0A                %7D finally %7B%0A                    STACK_DEPTH.set(d);%0A                %7D%0A            %7D
 %0A   
@@ -2377,38 +2377,290 @@
         
-failed0(exc, channel);
+Integer d = STACK_DEPTH.get();%0A            if (d %3C MAX_STACK_DEPTH) %7B%0A                STACK_DEPTH.set(d + 1);%0A                try %7B%0A                    failed0(exc, channel);%0A                %7D finally %7B%0A                    STACK_DEPTH.set(d);%0A                %7D%0A            %7D
 %0A       

Fix regression in AioCompletionHandler that leads to StackOverflowError