Netty學習(三)- Unsafe

目錄

 

1.概覽

1.1 介紹

2. 分析

2.1 Unsafe接口

2.2 Unsafe接口實現類

2.2.1 AbstractUnsafe

2.2.2 EpollServerSocketUnsafe


1.概覽

1.1 介紹

官方解釋

Unsafe operations that should never be called from user-code. These methods are only provided to implement the actual transport, and must be invoked from an I/O thread except for the following methods:

這個接口的方法主要用來做實際傳輸的,並且必須被一個IO線程調用,不能被開發者調用。

2. 分析

2.1 Unsafe接口

    public interface Unsafe {
        Handle recvBufAllocHandle();
 
        SocketAddress localAddress();
 
        SocketAddress remoteAddress();
 
        void register(EventLoop var1, ChannelPromise var2);
 
        void bind(SocketAddress var1, ChannelPromise var2);
 
        void connect(SocketAddress var1, SocketAddress var2, ChannelPromise var3);
 
        void disconnect(ChannelPromise var1);
 
        void close(ChannelPromise var1);
 
        void closeForcibly();
 
        void deregister(ChannelPromise var1);
 
        void beginRead();
 
        void write(Object var1, ChannelPromise var2);
 
        void flush();
 
        ChannelPromise voidPromise();
 
        ChannelOutboundBuffer outboundBuffer();
    }

 

2.2 Unsafe接口實現類

剛纔也說到了,Unsafe接口被作爲Channel接口的內部接口,那要看Unsafe接口的具體實現就必須到Channel接口的各個實現類去看看。Channel接口的實現類相當多,從idea導出

AbstractChannel (io.netty.channel)
    AbstractEpollChannel (io.netty.channel.epoll)
        AbstractEpollServerChannel (io.netty.channel.epoll)
            EpollServerDomainSocketChannel (io.netty.channel.epoll)
            EpollServerSocketChannel (io.netty.channel.epoll)
        AbstractEpollStreamChannel (io.netty.channel.epoll)
            EpollSocketChannel (io.netty.channel.epoll)
            EpollDomainSocketChannel (io.netty.channel.epoll)
        EpollDatagramChannel (io.netty.channel.epoll)
    LocalChannel (io.netty.channel.local)
    AbstractHttp2StreamChannel (io.netty.handler.codec.http2)
        Http2StreamChannel in Http2MultiplexCodec (io.netty.handler.codec.http2)
    EmbeddedChannel (io.netty.channel.embedded)
    AbstractOioChannel (io.netty.channel.oio)
        AbstractOioByteChannel (io.netty.channel.oio)
            OioByteStreamChannel (io.netty.channel.oio)
                OioSocketChannel (io.netty.channel.socket.oio)
                                    RxtxChannel (io.netty.channel.rxtx)
                            AbstractOioMessageChannel (io.netty.channel.oio)
            OioSctpServerChannel (io.netty.channel.sctp.oio)
                            OioServerSocketChannel (io.netty.channel.socket.oio)
                            OioSctpChannel (io.netty.channel.sctp.oio)
                            OioDatagramChannel (io.netty.channel.socket.oio)
                    AbstractServerChannel (io.netty.channel)
        LocalServerChannel (io.netty.channel.local)
    AbstractNioChannel (io.netty.channel.nio)
        AbstractNioMessageChannel (io.netty.channel.nio)
            NioDatagramChannel (io.netty.channel.socket.nio)
            NioUdtAcceptorChannel (io.netty.channel.udt.nio)
                NioUdtByteAcceptorChannel (io.netty.channel.udt.nio)
                                    NioUdtMessageAcceptorChannel (io.netty.channel.udt.nio)
                                NioSctpChannel (io.netty.channel.sctp.nio)
            NioSctpServerChannel (io.netty.channel.sctp.nio)
            NioServerSocketChannel (io.netty.channel.socket.nio)
            NioUdtMessageConnectorChannel (io.netty.channel.udt.nio)
                NioUdtMessageRendezvousChannel (io.netty.channel.udt.nio)
                            AbstractNioByteChannel (io.netty.channel.nio)
            NioSocketChannel (io.netty.channel.socket.nio)
                            NioUdtByteConnectorChannel (io.netty.channel.udt.nio)
                ServerChannel (io.netty.channel)
    ServerSocketChannel (io.netty.channel.socket)
        EpollServerSocketChannel (io.netty.channel.epoll)
        OioServerSocketChannel (io.netty.channel.socket.oio)
        NioServerSocketChannel (io.netty.channel.socket.nio)
    ServerDomainSocketChannel (io.netty.channel.unix)
        EpollServerDomainSocketChannel (io.netty.channel.epoll)
    AbstractEpollServerChannel (io.netty.channel.epoll)
        EpollServerDomainSocketChannel (io.netty.channel.epoll)
        EpollServerSocketChannel (io.netty.channel.epoll)
    SctpServerChannel (io.netty.channel.sctp)
        OioSctpServerChannel (io.netty.channel.sctp.oio)
        NioSctpServerChannel (io.netty.channel.sctp.nio)
    AbstractServerChannel (io.netty.channel)
        LocalServerChannel (io.netty.channel.local)
    UdtServerChannel (io.netty.channel.udt)
        NioUdtAcceptorChannel (io.netty.channel.udt.nio)
            NioUdtByteAcceptorChannel (io.netty.channel.udt.nio)
            NioUdtMessageAcceptorChannel (io.netty.channel.udt.nio)
SctpChannel (io.netty.channel.sctp)
    NioSctpChannel (io.netty.channel.sctp.nio)
    OioSctpChannel (io.netty.channel.sctp.oio)
UnixChannel (io.netty.channel.unix)
    AbstractEpollChannel (io.netty.channel.epoll)
        AbstractEpollServerChannel (io.netty.channel.epoll)
            EpollServerDomainSocketChannel (io.netty.channel.epoll)
            EpollServerSocketChannel (io.netty.channel.epoll)
        AbstractEpollStreamChannel (io.netty.channel.epoll)
            EpollSocketChannel (io.netty.channel.epoll)
                            EpollDomainSocketChannel (io.netty.channel.epoll)
                        EpollDatagramChannel (io.netty.channel.epoll)
    DomainSocketChannel (io.netty.channel.unix)
        EpollDomainSocketChannel (io.netty.channel.epoll)
    ServerDomainSocketChannel (io.netty.channel.unix)
        EpollServerDomainSocketChannel (io.netty.channel.epoll)
DatagramChannel (io.netty.channel.socket)
    NioDatagramChannel (io.netty.channel.socket.nio)
    OioDatagramChannel (io.netty.channel.socket.oio)
    EpollDatagramChannel (io.netty.channel.epoll)
DuplexChannel (io.netty.channel.socket)
    DomainSocketChannel (io.netty.channel.unix)
        EpollDomainSocketChannel (io.netty.channel.epoll)
    AbstractEpollStreamChannel (io.netty.channel.epoll)
        EpollSocketChannel (io.netty.channel.epoll)
        EpollDomainSocketChannel (io.netty.channel.epoll)
    SocketChannel (io.netty.channel.socket)
        EpollSocketChannel (io.netty.channel.epoll)
        NioSocketChannel (io.netty.channel.socket.nio)
        OioSocketChannel (io.netty.channel.socket.oio)
UdtChannel (io.netty.channel.udt)
    NioUdtByteConnectorChannel (io.netty.channel.udt.nio)
        NioUdtByteRendezvousChannel (io.netty.channel.udt.nio)
    NioUdtMessageConnectorChannel (io.netty.channel.udt.nio)
        NioUdtMessageRendezvousChannel (io.netty.channel.udt.nio)
    UdtServerChannel (io.netty.channel.udt)
        NioUdtAcceptorChannel (io.netty.channel.udt.nio)
            NioUdtByteAcceptorChannel (io.netty.channel.udt.nio)
            NioUdtMessageAcceptorChannel (io.netty.channel.udt.nio)

選幾個比較常用的Channel實現類看看對應的Unsafe接口實現。

2.2.1 AbstractUnsafe

AbstractUnsafe抽象類位於AbstractChannel內部。

看下它的方法

 
    protected abstract class AbstractUnsafe implements Unsafe {
        private volatile ChannelOutboundBuffer outboundBuffer = new ChannelOutboundBuffer(AbstractChannel.this);
        private Handle recvHandle;
        private boolean inFlush0;
        private boolean neverRegistered = true;
 
        protected AbstractUnsafe() {
        }
 
        private void assertEventLoop() {
            assert !AbstractChannel.this.registered || AbstractChannel.this.eventLoop.inEventLoop();
 
        }
 
        public Handle recvBufAllocHandle() {
            if(this.recvHandle == null) {
                this.recvHandle = AbstractChannel.this.config().getRecvByteBufAllocator().newHandle();
            }
 
            return this.recvHandle;
        }
 
        public final ChannelOutboundBuffer outboundBuffer() {
            return this.outboundBuffer;
        }
 
        public final SocketAddress localAddress() {
            return AbstractChannel.this.localAddress0();
        }
 
        public final SocketAddress remoteAddress() {
            return AbstractChannel.this.remoteAddress0();
        }
 
        public final void register(EventLoop eventLoop, final ChannelPromise promise) {
            if(eventLoop == null) {
                throw new NullPointerException("eventLoop");
            } else if(AbstractChannel.this.isRegistered()) {
                promise.setFailure(new IllegalStateException("registered to an event loop already"));
            } else if(!AbstractChannel.this.isCompatible(eventLoop)) {
                promise.setFailure(new IllegalStateException("incompatible event loop type: " + eventLoop.getClass().getName()));
            } else {
                AbstractChannel.this.eventLoop = eventLoop;
                if(eventLoop.inEventLoop()) {
                    this.register0(promise);
                } else {
                    try {
                        eventLoop.execute(new Runnable() {
                            public void run() {
                                AbstractUnsafe.this.register0(promise);
                            }
                        });
                    } catch (Throwable var4) {
                        AbstractChannel.logger.warn("Force-closing a channel whose registration task was not accepted by an event loop: {}", AbstractChannel.this, var4);
                        this.closeForcibly();
                        AbstractChannel.this.closeFuture.setClosed();
                        this.safeSetFailure(promise, var4);
                    }
                }
 
            }
        }
 
        private void register0(ChannelPromise promise) {
            try {
                if(!promise.setUncancellable() || !this.ensureOpen(promise)) {
                    return;
                }
 
                boolean t = this.neverRegistered;
                AbstractChannel.this.doRegister();
                this.neverRegistered = false;
                AbstractChannel.this.registered = true;
                AbstractChannel.this.pipeline.invokeHandlerAddedIfNeeded();
                this.safeSetSuccess(promise);
                AbstractChannel.this.pipeline.fireChannelRegistered();
                if(AbstractChannel.this.isActive()) {
                    if(t) {
                        AbstractChannel.this.pipeline.fireChannelActive();
                    } else if(AbstractChannel.this.config().isAutoRead()) {
                        this.beginRead();
                    }
                }
            } catch (Throwable var3) {
                this.closeForcibly();
                AbstractChannel.this.closeFuture.setClosed();
                this.safeSetFailure(promise, var3);
            }
 
        }
 
        public final void bind(SocketAddress localAddress, ChannelPromise promise) {
            this.assertEventLoop();
            if(promise.setUncancellable() && this.ensureOpen(promise)) {
                if(Boolean.TRUE.equals(AbstractChannel.this.config().getOption(ChannelOption.SO_BROADCAST)) && localAddress instanceof InetSocketAddress && !((InetSocketAddress)localAddress).getAddress().isAnyLocalAddress() && !PlatformDependent.isWindows() && !PlatformDependent.maybeSuperUser()) {
                    AbstractChannel.logger.warn("A non-root user can\'t receive a broadcast packet if the socket is not bound to a wildcard address; binding to a non-wildcard address (" + localAddress + ") anyway as requested.");
                }
 
                boolean wasActive = AbstractChannel.this.isActive();
 
                try {
                    AbstractChannel.this.doBind(localAddress);
                } catch (Throwable var5) {
                    this.safeSetFailure(promise, var5);
                    this.closeIfClosed();
                    return;
                }
 
                if(!wasActive && AbstractChannel.this.isActive()) {
                    this.invokeLater(new Runnable() {
                        public void run() {
                            AbstractChannel.this.pipeline.fireChannelActive();
                        }
                    });
                }
 
                this.safeSetSuccess(promise);
            }
        }
 
        public final void disconnect(ChannelPromise promise) {
            this.assertEventLoop();
            if(promise.setUncancellable()) {
                boolean wasActive = AbstractChannel.this.isActive();
 
                try {
                    AbstractChannel.this.doDisconnect();
                } catch (Throwable var4) {
                    this.safeSetFailure(promise, var4);
                    this.closeIfClosed();
                    return;
                }
 
                if(wasActive && !AbstractChannel.this.isActive()) {
                    this.invokeLater(new Runnable() {
                        public void run() {
                            AbstractChannel.this.pipeline.fireChannelInactive();
                        }
                    });
                }
 
                this.safeSetSuccess(promise);
                this.closeIfClosed();
            }
        }
 
        public final void close(ChannelPromise promise) {
            this.assertEventLoop();
            this.close(promise, AbstractChannel.CLOSE_CLOSED_CHANNEL_EXCEPTION, AbstractChannel.CLOSE_CLOSED_CHANNEL_EXCEPTION, false);
        }
 
        private void close(final ChannelPromise promise, final Throwable cause, final ClosedChannelException closeCause, final boolean notify) {
            if(promise.setUncancellable()) {
                final ChannelOutboundBuffer outboundBuffer = this.outboundBuffer;
                if(outboundBuffer == null) {
                    if(!(promise instanceof VoidChannelPromise)) {
                        AbstractChannel.this.closeFuture.addListener(new ChannelFutureListener() {
                            public void operationComplete(ChannelFuture future) throws Exception {
                                promise.setSuccess();
                            }
                        });
                    }
 
                } else if(AbstractChannel.this.closeFuture.isDone()) {
                    this.safeSetSuccess(promise);
                } else {
                    final boolean wasActive = AbstractChannel.this.isActive();
                    this.outboundBuffer = null;
                    Executor closeExecutor = this.prepareToClose();
                    if(closeExecutor != null) {
                        closeExecutor.execute(new Runnable() {
                            public void run() {
                                try {
                                    AbstractUnsafe.this.doClose0(promise);
                                } finally {
                                    AbstractUnsafe.this.invokeLater(new Runnable() {
                                        public void run() {
                                            outboundBuffer.failFlushed(cause, notify);
                                            outboundBuffer.close(closeCause);
                                            AbstractUnsafe.this.fireChannelInactiveAndDeregister(wasActive);
                                        }
                                    });
                                }
 
                            }
                        });
                    } else {
                        try {
                            this.doClose0(promise);
                        } finally {
                            outboundBuffer.failFlushed(cause, notify);
                            outboundBuffer.close(closeCause);
                        }
 
                        if(this.inFlush0) {
                            this.invokeLater(new Runnable() {
                                public void run() {
                                    AbstractUnsafe.this.fireChannelInactiveAndDeregister(wasActive);
                                }
                            });
                        } else {
                            this.fireChannelInactiveAndDeregister(wasActive);
                        }
                    }
 
                }
            }
        }
 
        private void doClose0(ChannelPromise promise) {
            try {
                AbstractChannel.this.doClose();
                AbstractChannel.this.closeFuture.setClosed();
                this.safeSetSuccess(promise);
            } catch (Throwable var3) {
                AbstractChannel.this.closeFuture.setClosed();
                this.safeSetFailure(promise, var3);
            }
 
        }
 
        private void fireChannelInactiveAndDeregister(boolean wasActive) {
            this.deregister(this.voidPromise(), wasActive && !AbstractChannel.this.isActive());
        }
 
        public final void closeForcibly() {
            this.assertEventLoop();
 
            try {
                AbstractChannel.this.doClose();
            } catch (Exception var2) {
                AbstractChannel.logger.warn("Failed to close a channel.", var2);
            }
 
        }
 
        public final void deregister(ChannelPromise promise) {
            this.assertEventLoop();
            this.deregister(promise, false);
        }
 
        private void deregister(final ChannelPromise promise, final boolean fireChannelInactive) {
            if(promise.setUncancellable()) {
                if(!AbstractChannel.this.registered) {
                    this.safeSetSuccess(promise);
                } else {
                    this.invokeLater(new Runnable() {
                        public void run() {
                            try {
                                AbstractChannel.this.doDeregister();
                            } catch (Throwable var5) {
                                AbstractChannel.logger.warn("Unexpected exception occurred while deregistering a channel.", var5);
                            } finally {
                                if(fireChannelInactive) {
                                    AbstractChannel.this.pipeline.fireChannelInactive();
                                }
 
                                if(AbstractChannel.this.registered) {
                                    AbstractChannel.this.registered = false;
                                    AbstractChannel.this.pipeline.fireChannelUnregistered();
                                }
 
                                AbstractUnsafe.this.safeSetSuccess(promise);
                            }
 
                        }
                    });
                }
            }
        }
 
        public final void beginRead() {
            this.assertEventLoop();
            if(AbstractChannel.this.isActive()) {
                try {
                    AbstractChannel.this.doBeginRead();
                } catch (final Exception var2) {
                    this.invokeLater(new Runnable() {
                        public void run() {
                            AbstractChannel.this.pipeline.fireExceptionCaught(var2);
                        }
                    });
                    this.close(this.voidPromise());
                }
 
            }
        }
 
        public final void write(Object msg, ChannelPromise promise) {
            this.assertEventLoop();
            ChannelOutboundBuffer outboundBuffer = this.outboundBuffer;
            if(outboundBuffer == null) {
                this.safeSetFailure(promise, AbstractChannel.WRITE_CLOSED_CHANNEL_EXCEPTION);
                ReferenceCountUtil.release(msg);
            } else {
                int size;
                try {
                    msg = AbstractChannel.this.filterOutboundMessage(msg);
                    size = AbstractChannel.this.pipeline.estimatorHandle().size(msg);
                    if(size < 0) {
                        size = 0;
                    }
                } catch (Throwable var6) {
                    this.safeSetFailure(promise, var6);
                    ReferenceCountUtil.release(msg);
                    return;
                }
 
                outboundBuffer.addMessage(msg, size, promise);
            }
        }
 
        public final void flush() {
            this.assertEventLoop();
            ChannelOutboundBuffer outboundBuffer = this.outboundBuffer;
            if(outboundBuffer != null) {
                outboundBuffer.addFlush();
                this.flush0();
            }
        }
 
        protected void flush0() {
            if(!this.inFlush0) {
                ChannelOutboundBuffer outboundBuffer = this.outboundBuffer;
                if(outboundBuffer != null && !outboundBuffer.isEmpty()) {
                    this.inFlush0 = true;
                    if(!AbstractChannel.this.isActive()) {
                        try {
                            if(AbstractChannel.this.isOpen()) {
                                outboundBuffer.failFlushed(AbstractChannel.FLUSH0_NOT_YET_CONNECTED_EXCEPTION, true);
                            } else {
                                outboundBuffer.failFlushed(AbstractChannel.FLUSH0_CLOSED_CHANNEL_EXCEPTION, false);
                            }
                        } finally {
                            this.inFlush0 = false;
                        }
 
                    } else {
                        try {
                            AbstractChannel.this.doWrite(outboundBuffer);
                        } catch (Throwable var11) {
                            if(var11 instanceof IOException && AbstractChannel.this.config().isAutoClose()) {
                                this.close(this.voidPromise(), var11, AbstractChannel.FLUSH0_CLOSED_CHANNEL_EXCEPTION, false);
                            } else {
                                outboundBuffer.failFlushed(var11, true);
                            }
                        } finally {
                            this.inFlush0 = false;
                        }
 
                    }
                }
            }
        }
 
        public final ChannelPromise voidPromise() {
            this.assertEventLoop();
            return AbstractChannel.this.unsafeVoidPromise;
        }
 
        /** @deprecated */
        @Deprecated
        protected final boolean ensureOpen(ChannelPromise promise) {
            if(AbstractChannel.this.isOpen()) {
                return true;
            } else {
                this.safeSetFailure(promise, AbstractChannel.ENSURE_OPEN_CLOSED_CHANNEL_EXCEPTION);
                return false;
            }
        }
 
        protected final void safeSetSuccess(ChannelPromise promise) {
            if(!(promise instanceof VoidChannelPromise) && !promise.trySuccess()) {
                AbstractChannel.logger.warn("Failed to mark a promise as success because it is done already: {}", promise);
            }
 
        }
 
        protected final void safeSetFailure(ChannelPromise promise, Throwable cause) {
            if(!(promise instanceof VoidChannelPromise) && !promise.tryFailure(cause)) {
                AbstractChannel.logger.warn("Failed to mark a promise as failure because it\'s done already: {}", promise, cause);
            }
 
        }
 
        protected final void closeIfClosed() {
            if(!AbstractChannel.this.isOpen()) {
                this.close(this.voidPromise());
            }
        }
 
        private void invokeLater(Runnable task) {
            try {
                AbstractChannel.this.eventLoop().execute(task);
            } catch (RejectedExecutionException var3) {
                AbstractChannel.logger.warn("Can\'t invoke task later as EventLoop rejected it", var3);
            }
 
        }
 
        protected final Throwable annotateConnectException(Throwable cause, SocketAddress remoteAddress) {
            return (Throwable)(cause instanceof ConnectException?new AbstractChannel.AnnotatedConnectException((ConnectException)cause, remoteAddress):(cause instanceof NoRouteToHostException?new AbstractChannel.AnnotatedNoRouteToHostException((NoRouteToHostException)cause, remoteAddress):(cause instanceof SocketException?new AbstractChannel.AnnotatedSocketException((SocketException)cause, remoteAddress):cause)));
        }
 
        protected Executor prepareToClose() {
            return null;
        }
    }

2.2.2 EpollServerSocketUnsafe

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章