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