// 
// Decompiled by Procyon v0.6.0
// 

package io.netty.channel;

import io.netty.util.internal.SystemPropertyUtil;
import io.netty.util.concurrent.EventExecutor;
import io.netty.util.internal.PlatformDependent;
import io.netty.util.concurrent.Promise;
import io.netty.util.concurrent.Future;
import java.util.Queue;
import java.util.concurrent.TimeUnit;
import io.netty.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.Executor;
import io.netty.util.concurrent.ThreadAwareExecutor;
import io.netty.util.internal.ObjectUtil;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

public class SingleThreadIoEventLoop extends SingleThreadEventLoop implements IoEventLoop
{
    private static final long DEFAULT_MAX_TASK_PROCESSING_QUANTUM_NS;
    private final long maxTaskProcessingQuantumNs;
    private final IoHandlerContext context;
    private final IoHandler ioHandler;
    private final AtomicInteger numRegistrations;
    
    public SingleThreadIoEventLoop(final IoEventLoopGroup parent, final ThreadFactory threadFactory, final IoHandlerFactory ioHandlerFactory) {
        super(parent, threadFactory, false, ObjectUtil.checkNotNull(ioHandlerFactory, "ioHandlerFactory").isChangingThreadSupported());
        this.context = new IoHandlerContext() {
            @Override
            public boolean canBlock() {
                assert SingleThreadIoEventLoop.this.inEventLoop();
                return !SingleThreadIoEventLoop.this.hasTasks() && !AbstractScheduledEventExecutor.this.hasScheduledTasks();
            }
            
            @Override
            public long delayNanos(final long currentTimeNanos) {
                assert SingleThreadIoEventLoop.this.inEventLoop();
                return SingleThreadEventExecutor.this.delayNanos(currentTimeNanos);
            }
            
            @Override
            public long deadlineNanos() {
                assert SingleThreadIoEventLoop.this.inEventLoop();
                return SingleThreadEventExecutor.this.deadlineNanos();
            }
            
            @Override
            public void reportActiveIoTime(final long activeNanos) {
                SingleThreadEventExecutor.this.reportActiveIoTime(activeNanos);
            }
            
            @Override
            public boolean shouldReportActiveIoTime() {
                return SingleThreadEventExecutor.this.isSuspensionSupported();
            }
        };
        this.numRegistrations = new AtomicInteger();
        this.maxTaskProcessingQuantumNs = SingleThreadIoEventLoop.DEFAULT_MAX_TASK_PROCESSING_QUANTUM_NS;
        this.ioHandler = ioHandlerFactory.newHandler(this);
    }
    
    public SingleThreadIoEventLoop(final IoEventLoopGroup parent, final Executor executor, final IoHandlerFactory ioHandlerFactory) {
        super(parent, executor, false, ObjectUtil.checkNotNull(ioHandlerFactory, "ioHandlerFactory").isChangingThreadSupported());
        this.context = new IoHandlerContext() {
            @Override
            public boolean canBlock() {
                assert SingleThreadIoEventLoop.this.inEventLoop();
                return !SingleThreadIoEventLoop.this.hasTasks() && !AbstractScheduledEventExecutor.this.hasScheduledTasks();
            }
            
            @Override
            public long delayNanos(final long currentTimeNanos) {
                assert SingleThreadIoEventLoop.this.inEventLoop();
                return SingleThreadEventExecutor.this.delayNanos(currentTimeNanos);
            }
            
            @Override
            public long deadlineNanos() {
                assert SingleThreadIoEventLoop.this.inEventLoop();
                return SingleThreadEventExecutor.this.deadlineNanos();
            }
            
            @Override
            public void reportActiveIoTime(final long activeNanos) {
                SingleThreadEventExecutor.this.reportActiveIoTime(activeNanos);
            }
            
            @Override
            public boolean shouldReportActiveIoTime() {
                return SingleThreadEventExecutor.this.isSuspensionSupported();
            }
        };
        this.numRegistrations = new AtomicInteger();
        this.maxTaskProcessingQuantumNs = SingleThreadIoEventLoop.DEFAULT_MAX_TASK_PROCESSING_QUANTUM_NS;
        this.ioHandler = ioHandlerFactory.newHandler(this);
    }
    
    public SingleThreadIoEventLoop(final IoEventLoopGroup parent, final ThreadFactory threadFactory, final IoHandlerFactory ioHandlerFactory, final int maxPendingTasks, final RejectedExecutionHandler rejectedExecutionHandler, final long maxTaskProcessingQuantumMs) {
        super(parent, threadFactory, false, ObjectUtil.checkNotNull(ioHandlerFactory, "ioHandlerFactory").isChangingThreadSupported(), maxPendingTasks, rejectedExecutionHandler);
        this.context = new IoHandlerContext() {
            @Override
            public boolean canBlock() {
                assert SingleThreadIoEventLoop.this.inEventLoop();
                return !SingleThreadIoEventLoop.this.hasTasks() && !AbstractScheduledEventExecutor.this.hasScheduledTasks();
            }
            
            @Override
            public long delayNanos(final long currentTimeNanos) {
                assert SingleThreadIoEventLoop.this.inEventLoop();
                return SingleThreadEventExecutor.this.delayNanos(currentTimeNanos);
            }
            
            @Override
            public long deadlineNanos() {
                assert SingleThreadIoEventLoop.this.inEventLoop();
                return SingleThreadEventExecutor.this.deadlineNanos();
            }
            
            @Override
            public void reportActiveIoTime(final long activeNanos) {
                SingleThreadEventExecutor.this.reportActiveIoTime(activeNanos);
            }
            
            @Override
            public boolean shouldReportActiveIoTime() {
                return SingleThreadEventExecutor.this.isSuspensionSupported();
            }
        };
        this.numRegistrations = new AtomicInteger();
        this.maxTaskProcessingQuantumNs = ((ObjectUtil.checkPositiveOrZero(maxTaskProcessingQuantumMs, "maxTaskProcessingQuantumMs") == 0L) ? SingleThreadIoEventLoop.DEFAULT_MAX_TASK_PROCESSING_QUANTUM_NS : TimeUnit.MILLISECONDS.toNanos(maxTaskProcessingQuantumMs));
        this.ioHandler = ioHandlerFactory.newHandler(this);
    }
    
    public SingleThreadIoEventLoop(final IoEventLoopGroup parent, final Executor executor, final IoHandlerFactory ioHandlerFactory, final int maxPendingTasks, final RejectedExecutionHandler rejectedExecutionHandler, final long maxTaskProcessingQuantumMs) {
        super(parent, executor, false, ObjectUtil.checkNotNull(ioHandlerFactory, "ioHandlerFactory").isChangingThreadSupported(), maxPendingTasks, rejectedExecutionHandler);
        this.context = new IoHandlerContext() {
            @Override
            public boolean canBlock() {
                assert SingleThreadIoEventLoop.this.inEventLoop();
                return !SingleThreadIoEventLoop.this.hasTasks() && !AbstractScheduledEventExecutor.this.hasScheduledTasks();
            }
            
            @Override
            public long delayNanos(final long currentTimeNanos) {
                assert SingleThreadIoEventLoop.this.inEventLoop();
                return SingleThreadEventExecutor.this.delayNanos(currentTimeNanos);
            }
            
            @Override
            public long deadlineNanos() {
                assert SingleThreadIoEventLoop.this.inEventLoop();
                return SingleThreadEventExecutor.this.deadlineNanos();
            }
            
            @Override
            public void reportActiveIoTime(final long activeNanos) {
                SingleThreadEventExecutor.this.reportActiveIoTime(activeNanos);
            }
            
            @Override
            public boolean shouldReportActiveIoTime() {
                return SingleThreadEventExecutor.this.isSuspensionSupported();
            }
        };
        this.numRegistrations = new AtomicInteger();
        this.maxTaskProcessingQuantumNs = ((ObjectUtil.checkPositiveOrZero(maxTaskProcessingQuantumMs, "maxTaskProcessingQuantumMs") == 0L) ? SingleThreadIoEventLoop.DEFAULT_MAX_TASK_PROCESSING_QUANTUM_NS : TimeUnit.MILLISECONDS.toNanos(maxTaskProcessingQuantumMs));
        this.ioHandler = ioHandlerFactory.newHandler(this);
    }
    
    protected SingleThreadIoEventLoop(final IoEventLoopGroup parent, final Executor executor, final IoHandlerFactory ioHandlerFactory, final Queue<Runnable> taskQueue, final Queue<Runnable> tailTaskQueue, final RejectedExecutionHandler rejectedExecutionHandler) {
        super(parent, executor, false, ObjectUtil.checkNotNull(ioHandlerFactory, "ioHandlerFactory").isChangingThreadSupported(), taskQueue, tailTaskQueue, rejectedExecutionHandler);
        this.context = new IoHandlerContext() {
            @Override
            public boolean canBlock() {
                assert SingleThreadIoEventLoop.this.inEventLoop();
                return !SingleThreadIoEventLoop.this.hasTasks() && !AbstractScheduledEventExecutor.this.hasScheduledTasks();
            }
            
            @Override
            public long delayNanos(final long currentTimeNanos) {
                assert SingleThreadIoEventLoop.this.inEventLoop();
                return SingleThreadEventExecutor.this.delayNanos(currentTimeNanos);
            }
            
            @Override
            public long deadlineNanos() {
                assert SingleThreadIoEventLoop.this.inEventLoop();
                return SingleThreadEventExecutor.this.deadlineNanos();
            }
            
            @Override
            public void reportActiveIoTime(final long activeNanos) {
                SingleThreadEventExecutor.this.reportActiveIoTime(activeNanos);
            }
            
            @Override
            public boolean shouldReportActiveIoTime() {
                return SingleThreadEventExecutor.this.isSuspensionSupported();
            }
        };
        this.numRegistrations = new AtomicInteger();
        this.maxTaskProcessingQuantumNs = SingleThreadIoEventLoop.DEFAULT_MAX_TASK_PROCESSING_QUANTUM_NS;
        this.ioHandler = ioHandlerFactory.newHandler(this);
    }
    
    @Override
    protected void run() {
        assert this.inEventLoop();
        this.ioHandler.initialize();
        do {
            this.runIo();
            if (this.isShuttingDown()) {
                this.ioHandler.prepareToDestroy();
            }
            this.runAllTasks(this.maxTaskProcessingQuantumNs);
        } while (!this.confirmShutdown() && !this.canSuspend());
    }
    
    protected final IoHandler ioHandler() {
        return this.ioHandler;
    }
    
    @Override
    protected boolean canSuspend(final int state) {
        return super.canSuspend(state) && this.numRegistrations.get() == 0;
    }
    
    protected int runIo() {
        assert this.inEventLoop();
        return this.ioHandler.run(this.context);
    }
    
    @Override
    public IoEventLoop next() {
        return this;
    }
    
    @Override
    public final Future<IoRegistration> register(final IoHandle handle) {
        final Promise<IoRegistration> promise = this.newPromise();
        if (this.inEventLoop()) {
            this.registerForIo0(handle, promise);
        }
        else {
            this.execute(() -> this.registerForIo0(handle, promise));
        }
        return promise;
    }
    
    @Override
    protected int getNumOfRegisteredChannels() {
        return this.numRegistrations.get();
    }
    
    private void registerForIo0(final IoHandle handle, final Promise<IoRegistration> promise) {
        assert this.inEventLoop();
        IoRegistration registration;
        try {
            registration = this.ioHandler.register(handle);
        }
        catch (final Exception e) {
            promise.setFailure(e);
            return;
        }
        this.numRegistrations.incrementAndGet();
        promise.setSuccess(new IoRegistrationWrapper(registration));
    }
    
    @Override
    protected final void wakeup(final boolean inEventLoop) {
        this.ioHandler.wakeup();
    }
    
    @Override
    protected final void cleanup() {
        assert this.inEventLoop();
        this.ioHandler.destroy();
    }
    
    @Override
    public boolean isCompatible(final Class<? extends IoHandle> handleType) {
        return this.ioHandler.isCompatible(handleType);
    }
    
    @Override
    public boolean isIoType(final Class<? extends IoHandler> handlerType) {
        return this.ioHandler.getClass().equals(handlerType);
    }
    
    @Override
    protected Queue<Runnable> newTaskQueue(final int maxPendingTasks) {
        return newTaskQueue0(maxPendingTasks);
    }
    
    protected static Queue<Runnable> newTaskQueue0(final int maxPendingTasks) {
        return (maxPendingTasks == Integer.MAX_VALUE) ? PlatformDependent.newMpscQueue() : PlatformDependent.newMpscQueue(maxPendingTasks);
    }
    
    static {
        DEFAULT_MAX_TASK_PROCESSING_QUANTUM_NS = TimeUnit.MILLISECONDS.toNanos(Math.max(100, SystemPropertyUtil.getInt("io.netty.eventLoop.maxTaskProcessingQuantumMs", 1000)));
    }
    
    private final class IoRegistrationWrapper implements IoRegistration
    {
        private final IoRegistration registration;
        
        IoRegistrationWrapper(final IoRegistration registration) {
            this.registration = registration;
        }
        
        @Override
        public <T> T attachment() {
            return this.registration.attachment();
        }
        
        @Override
        public long submit(final IoOps ops) {
            return this.registration.submit(ops);
        }
        
        @Override
        public boolean isValid() {
            return this.registration.isValid();
        }
        
        @Override
        public boolean cancel() {
            if (this.registration.cancel()) {
                SingleThreadIoEventLoop.this.numRegistrations.decrementAndGet();
                return true;
            }
            return false;
        }
    }
}
