docs: def close(self, reply_code=0, reply_text='', class_id=0, method_id=0):
          '''
          Close this channel.  Caller has the option of specifying the reason for
          closure and the class and method ids of the current frame in which an
          error occurred.  If in the event of an exception, the channel will be
          marked as immediately closed.  If channel is already closed, call is
          ignored.
          '''
          if not getattr(self, 'channel', None) or self.channel._closed:
              return
  
          self.channel._close_info = {
              'reply_code': reply_code,
              'reply_text': reply_text,
              'class_id': class_id,
              'method_id': method_id
          }
  
          # exceptions here likely due to race condition as connection is closing
          # cap the reply_text we send because it may be arbitrarily long
          try:
              args = Writer()
              args.write_short(reply_code)
              args.write_shortstr(reply_text[:255])
              args.write_short(class_id)
              args.write_short(method_id)
              self.send_frame(MethodFrame(self.channel_id, 20, 40, args))
  
              self.channel.add_synchronous_cb(self._recv_close_ok)
          finally:
              # Immediately set the closed flag so no more frames can be sent
              # NOTE: in synchronous mode, by the time this is called we will
              # have already run self.channel._closed_cb and so the channel
              # reference is gone.
              if self.channel:
                  self.channel._closed = True