docs: def _memoize(self, handler, memoize, timeout, *args, **kw):
          """ Caches the execution result of successful executions        
          hash = hash(handler)
          memoize = { 
              hash : ((args, kw, result), (args, kw, result), ...), 
              hash : ((args, kw, result), ...), ...                       
          }
          """
          if not isinstance(handler, Event) and self.sender is not None:
              args = list(args)[:]
              args.insert(0, self.sender)
  
          if not memoize:  # no caching
  
              if timeout <= 0:  # no time restriction
                  return True, handler(*args, **kw), handler
  
              result = self._timeout(timeout, handler, *args, **kw)
              if isinstance(result, tuple) and len(result) == 3:
                  if isinstance(result[1], Exception):  # error occurred
                      return False, self._error(result), handler
              return True, result, handler
  
          else:  # caching
              with self._mlock:  # cache structure lock
                  hash_ = hash(handler)
                  if hash_ in self.memoize:
                      for args_, kw_, result in self.memoize[hash_]:
                          if args_ == args and kw_ == kw:  # shallow structure comparison only
                              return True, result, handler
  
                  if timeout <= 0:  # no time restriction
                      result = handler(*args, **kw)
                  else:
                      result = self._timeout(timeout, handler, *args, **kw)
                      if isinstance(result, tuple) and len(result) == 3:
                          if isinstance(result[1], Exception):  # error occurred
                              return False, self._error(result), handler
  
                  if hash_ not in self.memoize:
                      self.memoize[hash_] = []
                  self.memoize[hash_].append((args, kw, result))
                  return True, result, handler