docstr: Add a send event, returning the corresponding Future
docstr_tok: ["Add","a","send","event",",","returning","the","corresponding","Future"]
code: def _add_send_event(self, kind, msg=None, kwargs=None, future=None):
      """Add a send event, returning the corresponding Future"""
      f = future or self._Future()
      # attempt send with DONTWAIT if no futures are waiting
      # short-circuit for sends that will resolve immediately
      # only call if no send Futures are waiting
      if kind in ("send", "send_multipart") and not self._send_futures:
          flags = kwargs.get("flags", 0)
          nowait_kwargs = kwargs.copy()
          nowait_kwargs["flags"] = flags | _zmq.DONTWAIT
  
          # short-circuit non-blocking calls
          send = getattr(self._shadow_sock, kind)
          # track if the send resolved or not
          # (EAGAIN if DONTWAIT is not set should proceed with)
          finish_early = True
          try:
              r = send(msg, **nowait_kwargs)
          except _zmq.Again as e:
              if flags & _zmq.DONTWAIT:
                  f.set_exception(e)
              else:
                  # EAGAIN raised and DONTWAIT not requested,
                  # proceed with async send
                  finish_early = False
          except Exception as e:
              f.set_exception(e)
          else:
              f.set_result(r)
  
          if finish_early:
              # short-circuit resolved, return finished Future
              # schedule wake for recv if there are any receivers waiting
              if self._recv_futures:
                  self._schedule_remaining_events()
              return f
  
      # we add it to the list of futures before we add the timeout as the
      # timeout will remove the future from recv_futures to avoid leaks
      self._send_futures.append(
          _FutureEvent(f, kind, kwargs=kwargs, msg=msg)
      )
      # Don't let the Future sit in _send_futures after it's done
      f.add_done_callback(
          lambda f: self._remove_finished_future(f, self._send_futures)
      )
  
      if hasattr(_zmq, "SNDTIMEO"):
          timeout_ms = self._shadow_sock.get(_zmq.SNDTIMEO)
          if timeout_ms >= 0:
              self._add_timeout(f, timeout_ms * 1e-3)
  
      self._add_io_state(POLLOUT)
      return f
  
imports: from collections import namedtuple, deque
  from itertools import chain
  from zmq import EVENTS, POLLOUT, POLLIN
  import zmq
label_desc: Use image node_id 15 for calling the _AsyncSocket obj's underlying member method code with example usage: obj._add_send_event(kind, msg, kwargs, future) and returns: f, f