'Caches the execution result of successful executions
hash = self.hash(handler)
memoize = {
hash : ((args, kwargs, result), (args, kwargs, result), ...),
hash : ((args, kwargs, result), ...), ...'

def _memoize(self, memoize, timeout, handler, *args, **kwargs):

    if ((not isinstance(handler, Event)) and (self.sender is not None)):
        args = list(args)[:]
        args.insert(0, self.sender)
    if (not memoize):
        if (timeout <= 0):
            result = [True, handler(*args, **kwargs), handler]
            return result
        result = self._timeout(timeout, handler, *args, **kwargs)
        if (isinstance(result, tuple) and (len(result) == 3)):
            if isinstance(result[1], Exception):
                return [False, self._error(result), handler]
        return [True, result, handler]
    else:
        hash_ = self.hash(handler)
        if (hash_ in self.memoize):
            for (args_, kwargs_, result) in self.memoize[hash_]:
                if ((args_ == args) and (kwargs_ == kwargs)):
                    return [True, result, handler]
        if (timeout <= 0):
            result = handler(*args, **kwargs)
        else:
            result = self._timeout(timeout, handler, *args, **kwargs)
            if (isinstance(result, tuple) and (len(result) == 3)):
                if isinstance(result[1], Exception):
                    return [False, self._error(result), handler]
        lock = threading.RLock()
        lock.acquire()
        try:
            if (hash_ not in self.memoize):
                self.memoize[hash_] = []
            self.memoize[hash_].append((args, kwargs, result))
            return [True, result, handler]
        finally:
            lock.release()
