@Override public void run() { loop: while (true) { OutputState state = _state.get(); if (_onError != null) { switch (state) { case CLOSED: case ERROR: { _onError = null; break loop; } default: { if (_state.compareAndSet(state, OutputState.ERROR)) { Throwable th = _onError; _onError = null; if (LOG.isDebugEnabled()) LOG.debug("onError", th); _writeListener.onError(th); close(); break loop; } } } continue; } switch (_state.get()) { case CLOSED: // Even though a write is not possible, because a close has // occurred, we need to call onWritePossible to tell async // producer that the last write completed. // So fall through case PENDING: case UNREADY: case READY: try { _writeListener.onWritePossible(); break loop; } catch (Throwable e) { _onError = e; } break; default: _onError = new IllegalStateException("state=" + _state.get()); } } }
/** * Called to indicate that the last write has been performed. It updates the state and performs * cleanup operations. */ void closed() { while (true) { OutputState state = _state.get(); switch (state) { case CLOSED: { return; } case UNREADY: { if (_state.compareAndSet(state, OutputState.ERROR)) _writeListener.onError( _onError == null ? new EofException("Async closed") : _onError); break; } default: { if (!_state.compareAndSet(state, OutputState.CLOSED)) break; try { _channel.getResponse().closeOutput(); } catch (Throwable x) { if (LOG.isDebugEnabled()) LOG.debug(x); abort(x); } finally { releaseBuffer(); } // Return even if an exception is thrown by closeOutput(). return; } } } }
@Override public void run() { if (_onError != null) { Throwable th = _onError; _onError = null; _writeListener.onError(th); close(); } if (_state.get() == State.READY) { try { _writeListener.onWritePossible(); } catch (Throwable e) { _writeListener.onError(e); close(); } } }
@Override public void setWriteListener(WriteListener listener) { try { // writes are immediately and always possible due to the // use of the chunks deque listener.onWritePossible(); } catch (IOException ioe) { // doesn't make sense to do anything but ignore if // the coupled listener fails } }
public void onWritePossible() throws IOException { // Any buffered data left over from a previous non-blocking write is // written in the Processor so if this point is reached the app is able // to write data. boolean fire = false; synchronized (nonBlockingStateLock) { registeredForWrite = false; if (fireListener) { fireListener = false; fire = true; } } if (fire) { listener.onWritePossible(); } }