code: def _add_io_state(self, state: int) -> None:
          
          if self.closed():
              # connection has been closed, so there can be no future events
              return
          if self._state is None:
              self._state = ioloop.IOLoop.ERROR | state
              self.io_loop.add_handler(self.fileno(), self._handle_events, self._state)
          elif not self._state & state:
              self._state = self._state | state
              self.io_loop.update_handler(self.fileno(), self._state)
docs: Adds `state` (IOLoop.{READ,WRITE} flags) to our event handler.
  
          Implementation notes: Reads and writes have a fast path and a
          slow path.  The fast path reads synchronously from socket
          buffers, while the slow path uses `_add_io_state` to schedule
          an IOLoop callback.
  
          To detect closed connections, we must have called
          `_add_io_state` at some point, but we want to delay this as
          much as possible so we don't have to set an `IOLoop.ERROR`
          listener that will be overwritten by the next slow-path
          operation. If a sequence of fast-path ops do not end in a
          slow-path op, (e.g. for an @asynchronous long-poll request),
          we must add the error handler.
  
          TODO: reevaluate this now that callbacks are gone.