docs: def fire(self, *args, **kw):
          """ Stores all registered handlers in a queue for processing """
          result = []
  
          with self._hlock:
              handlers = self.handlers
  
          if self.threads == 0:  # same-thread execution - synchronized
              for k in handlers:
                  # handler, memoize, timeout
                  h, m, t = handlers[k]
                  try:
                      r = self._memoize(h, m, t, *args, **kw)
                      result.append(tuple(r))
                  except:
                      result.append((False, self._error(sys.exc_info()), h))
  
          elif self.threads > 0:  # multi-thread execution - desynchronized if self.threads > 1
              queue = Queue()
  
              # result lock just in case [].append() is not  
              # thread-safe in other Python implementations
              rlock = RLock()
  
              def _execute(*args, **kw):
                  """ Executes all handlers stored in the queue """
                  while True:
                      try:
                          item = queue.get()
                          if item is None:
                              queue.task_done()
                              break
  
                          # handler, memoize, timeout
                          h, m, t = handlers[item]  # call under active lock
  
                          try:
                              r = self._memoize(h, m, t, *args, **kw)
                              if not self.asynch:
                                  with rlock:
                                      result.append(tuple(r))
                          except:
                              if not self.asynch:
                                  with rlock:
                                      result.append((False, self._error(sys.exc_info()), h))
  
                          queue.task_done()
  
                      except Empty:  # never triggered, just to be safe
                          break
  
              if handlers:
                  threads = self._threads(handlers=handlers)
  
                  for _ in range(threads):
                      t = Thread(target=_execute, args=args, kwargs=kw)
                      t.daemon = True
                      t.start()
  
                  for k in handlers:
                      queue.put(k)
  
                      if self.asynch:  # main thread, no locking required
                          h, _, _ = handlers[k]
                          result.append((None, None, h))
  
                  for _ in range(threads):
                      queue.put(None)  # stop each worker
  
                  if not self.asynch:
                      queue.join()
  
          return tuple(result) or None