/**
   * Returns a successful buffer read request.
   *
   * <p>Note: This method is always called from the same I/O thread.
   */
  private void returnBufferFromIOThread(Buffer buffer) {
    final NotificationListener listener;

    synchronized (lock) {
      if (hasReachedEndOfFile || isReleased) {
        buffer.recycle();

        return;
      }

      returnedBuffers.add(buffer);

      listener = registeredListener;
      registeredListener = null;

      // If this was the last buffer before we reached EOF, set the corresponding flag to
      // ensure that further buffers are correctly recycled and eventually no further reads
      // are triggered.
      if (asyncFileReader.hasReachedEndOfFile()) {
        hasReachedEndOfFile = true;
      }
    }

    if (listener != null) {
      listener.onNotification();
    }
  }
  /** Notifies the view about an error. */
  private void notifyError(IOException error) {
    if (errorInIOThread == null) {
      errorInIOThread = error;
    }

    final NotificationListener listener;

    synchronized (lock) {
      listener = registeredListener;
      registeredListener = null;
    }

    if (listener != null) {
      listener.onNotification();
    }
  }