def singledispatch(function):
    registry = {}
    dispatch_cache = WeakKeyDictionary()
    def ns():
        pass
    ns.cache_token = None
    def dispatch(cls):
        if ns.cache_token is not None:
            current_token = get_cache_token()
            if ns.cache_token != current_token:
                dispatch_cache.clear()
                ns.cache_token = current_token
        try:
            impl = dispatch_cache[cls]
        except KeyError:
            try:
                impl = registry[cls]
            except KeyError:
                impl = _find_impl(cls, registry)
            dispatch_cache[cls] = impl
        return impl
    def register(cls, func=None):
        if func is None:
            return lambda f: register(cls, f)
        registry[cls] = func
        if ns.cache_token is None and hasattr(cls, '__abstractmethods__'):
            ns.cache_token = get_cache_token()
        dispatch_cache.clear()
        return func
    def wrapper(*args, **kw):
        return dispatch(args[0].__class__)(*args, **kw)
    registry[object] = function
    wrapper.register = register
    wrapper.dispatch = dispatch
    wrapper.registry = MappingProxyType(registry)
    wrapper._clear_cache = dispatch_cache.clear
    update_wrapper(wrapper, function)
    return wrapper