@SuppressWarnings("deprecation")
        protected void flush0() {
            if (inFlush0) {
                // Avoid re-entrance
                return;
            }

            final ChannelOutboundBuffer outboundBuffer = this.outboundBuffer;
            if (outboundBuffer == null || outboundBuffer.isEmpty()) {
                return;
            }

            inFlush0 = true;

            // Mark all pending write requests as failure if the channel is inactive.
            if (!isActive()) {
                try {
                    if (isOpen()) {
                        callFailFlushed(true);
                    } else {
                        // Do not trigger channelWritabilityChanged because the channel is closed already.
                        callFailFlushed(false);
                    }
                } finally {
                    inFlush0 = false;
                }
                return;
            }

            try {
                doWrite(outboundBuffer);
            } catch (Throwable t) {
                if (t instanceof IOException && config().isAutoClose()) {
                    /**
                     * Just call {@link #close(ChannelPromise, Throwable, boolean)} here which will take care of
                     * failing all flushed messages and also ensure the actual close of the underlying transport
                     * will happen before the promises are notified.
                     *
                     * This is needed as otherwise {@link #isActive()} , {@link #isOpen()} and {@link #isWritable()}
                     * may still return {@code true} even if the channel should be closed as result of the exception.
                     */
                    initialCloseCause = t;
                    close(voidPromise());
                    throw new RuntimeException("Unable to flush", t);
                } else {
                    try {
                        shutdownOutput(voidPromise());
                        throw new RuntimeException("Unable to flush", t);
                    } catch (Throwable t2) {
                        initialCloseCause = t;
                        close(voidPromise());
                        throw new RuntimeException("Unable to flush", t);
                    }
                }
            } finally {
                inFlush0 = false;
            }
        }
Copied and adapted from {@link io.netty.channel.nio.AbstractNioChannel.AbstractNioUnsafe}
plc4j/transports/serial/src/main/java/org/apache/plc4x/java/transport/serial/SerialChannel.java