@Override
 public void onNext(final Object w) {
   if (w == null) {
     throw Exceptions.argumentIsNullException();
   }
   if (subscription == null) {
     throw Exceptions.failWithCancel();
   }
   try {
     ChannelFuture cf = doOnWrite(w, ctx);
     lastWrite = cf;
     if (cf != null && log.isDebugEnabled()) {
       cf.addListener(
           new ChannelFutureListener() {
             @Override
             public void operationComplete(ChannelFuture future) throws Exception {
               if (!future.isSuccess()) {
                 log.error("write error :" + w, future.cause());
                 if (ByteBuf.class.isAssignableFrom(w.getClass())) {
                   ((ByteBuf) w).resetReaderIndex();
                 }
               }
             }
           });
     }
   } catch (Throwable t) {
     log.error("Write error for " + w, t);
     onError(t);
   }
 }
 @Override
 public void onError(Throwable t) {
   if (t == null) {
     throw Exceptions.argumentIsNullException();
   }
   if (subscription == null) {
     throw new IllegalStateException("already flushed", t);
   }
   log.error("Write error", t);
   subscription = null;
   ctx.channel().closeFuture().removeListener(this);
   doOnTerminate(ctx, null, promise, t);
 }
 @Override
 public void onNext(Object w) {
   if (w == null) {
     throw Exceptions.argumentIsNullException();
   }
   if (subscription == null) {
     throw Exceptions.failWithCancel();
   }
   try {
     ChannelFuture cf = doOnWrite(w, ctx);
     if (cf != null) {
       cf.addListener(writeListener);
     }
     ctx.flush();
   } catch (Throwable t) {
     log.error("Write error for " + w, t);
     onError(t);
     throw Exceptions.failWithCancel();
   }
 }