def METHOD_NAME(user_function):
    cache = dict()
    stats = [0, 0]  # make statistics updateable non-locally
    HITS, MISSES = 0, 1  # names for the stats fields
    make_key = _make_key
    cache_get = cache.get  # bound method to lookup key or return None
    _len = len  # localize the global len() function
    lock = RLock()  # because linkedlist updates aren't threadsafe
    root = []  # root of the circular doubly linked list
    root[:] = [root, root, None, None]  # initialize by pointing to self
    nonlocal_root = [root]  # make updateable non-locally
    PREV, NEXT, KEY, RESULT = 0, 1, 2, 3  # names for the link fields
    if maxsize == 0:
        def wrapper(*args, **kwds):
            # no caching, just do a statistics update after a successful call
            result = user_function(*args, **kwds)
            stats[MISSES] += 1
            return result
    elif maxsize is None:
        def wrapper(*args, **kwds):
            # simple caching without ordering or size limit
            key = make_key(args, kwds, typed)
            result = cache_get(
                key, root
            )  # root used here as a unique not-found sentinel
            if result is not root:
                stats[HITS] += 1
                return result
            result = user_function(*args, **kwds)
            cache[key] = result
            stats[MISSES] += 1
            return result
    else:
        def wrapper(*args, **kwds):
            # size limited caching that tracks accesses by recency
            key = make_key(args, kwds, typed) if kwds or typed else args
            with lock:
                link = cache_get(key)
                if link is not None:
                    # record recent use of the key by moving it
                    # to the front of the list
                    (root,) = nonlocal_root
                    link_prev, link_next, key, result = link
                    link_prev[NEXT] = link_next
                    link_next[PREV] = link_prev
                    last = root[PREV]
                    last[NEXT] = root[PREV] = link
                    link[PREV] = last
                    link[NEXT] = root
                    stats[HITS] += 1
                    return result
            result = user_function(*args, **kwds)
            with lock:
                (root,) = nonlocal_root
                if key in cache:
                    # getting here means that this same key was added to the
                    # cache while the lock was released.  since the link
                    # update is already done, we need only return the
                    # computed result and update the count of misses.
                    pass
                elif _len(cache) >= maxsize:
                    # use the old root to store the new key and result
                    oldroot = root
                    oldroot[KEY] = key
                    oldroot[RESULT] = result
                    # empty the oldest link and make it the new root
                    root = nonlocal_root[0] = oldroot[NEXT]
                    oldkey = root[KEY]
                    root[KEY] = root[RESULT] = None
                    # now update the cache dictionary for the new links
                    del cache[oldkey]
                    cache[key] = oldroot
                else:
                    # put result in a new link at the front of the list
                    last = root[PREV]
                    link = [last, root, key, result]
                    last[NEXT] = root[PREV] = cache[key] = link
                stats[MISSES] += 1
            return result
    def cache_info():
        """Report cache statistics"""
        with lock:
            return _CacheInfo(stats[HITS], stats[MISSES], maxsize, len(cache))
    def cache_clear():
        """Clear the cache and cache statistics"""
        with lock:
            cache.clear()
            root = nonlocal_root[0]
            root[:] = [root, root, None, None]
            stats[:] = [0, 0]
    wrapper.__wrapped__ = user_function
    wrapper.cache_info = cache_info
    wrapper.cache_clear = cache_clear
    return update_wrapper(wrapper, user_function)