def cache(time_to_wait = None, resource_manager = None):
    class cache_obj(object):
        def __init__(self, func):
            super(cache_obj,self).__init__()
            self.func         = (func,)
            self.lock         = threading.RLock()
            self.dictionaries_per_inst = {
                    # inst : { # if it's not an inst, None is the key
                    #   'dict': {},
                    #   'list': []
                    # }
                 }
            self._time        = time_to_wait
            self._inst        = None
            _cache_registry.append(self)

        def __get__(self, inst, owner):
            if inst is not None:
                self._inst = weakref.ref(inst)
            return self

        def _generate_key(self, args, kargs):
            if kargs == {}:
                try:
                    hash(args)
                except TypeError:
                    pass
                else:
                    key = _HasheableKey(args)
                    return key
            try:
                pickled_key = pickle.dumps((args,kargs))
            except:
                key = _NotPicklableKey((args,kargs))
            else:
                key = _PicklableKey(pickled_key)
            return key

        def _get_time(self):
            # For testing purposes
            return time_module.time()

        def __call__(self, *args, **kargs):
            key = self._generate_key(args, kargs)
            current_time = self._get_time()

            found, (obj, storage_time) = key.load(self._get_dictionaries())
            if found:
                if self.time is None or current_time - storage_time < self.time:
                    return obj

            if self._inst != None:
                args = (self._inst(),) + args
            return_value = self.func[0](*args, **kargs)

            key.save(
                    self._get_dictionaries(),
                    ( return_value, current_time)
                )

            return return_value

        def _save_to_cache(self, key, value):
            return_value, current_time = value
            key.save(self._get_dictionaries(), (return_value, current_time))

        def _get_dictionaries(self, inst = "this.is.not.an.instance"):
            if inst == "this.is.not.an.instance":
                inst = self._inst
            if not inst in self.dictionaries_per_inst:
                self.lock.acquire()
                try:
                    # Double ask, just to avoid acquiring and releasing
                    # without need
                    if not inst in self.dictionaries_per_inst:
                        self.dictionaries_per_inst[inst] = {
                            'dict' : {},
                            'list' : []
                        }
                finally:
                    self.lock.release()
            return self.dictionaries_per_inst[inst]

        def get_time(self):
            return self._time

        def set_time(self, value):
            self._time = value

        time = property(get_time, set_time)

        def _remove_obj(self, key, inst):
            try:
                returnValue, _ = key.pop(self._get_dictionaries(inst))
            except KeyError:
                return

    def wrapped_decorator(func):
        o = cache_obj(func)
        o.__name__ = func.__name__
        o.__doc__  = func.__doc__
        return o

    return wrapped_decorator
Test if sync strategy argument has ``name`` and ``dest`` but the
dataset/ETHPy150Open weblabdeusto/weblabdeusto/server/src/voodoo/cache.py/cache--crossover with--dataset/ETHPy150Open aws/aws-cli/tests/unit/customizations/s3/syncstrategy/test_base.py/TestBaseSync.test_no_use_sync_strategy_for_dest_but_only_name_in_params