What you want is to acquire a lock if the cache is empty, check if another thread has filled the cache while you where waiting on the lock, call the function, fill the cache and return. I don’t see how you could implement that with two independent decorators without locking all accesses (before `once`) or having the chance that it’s called more than once (after `once`). Tom
On 29 Apr 2020, at 08:15, Andrew Barnert via Python-ideas <python-ideas@python.org> wrote:
On Apr 28, 2020, at 16:25, Steven D'Aprano <steve@pearwood.info> wrote:
On Tue, Apr 28, 2020 at 11:45:49AM -0700, Raymond Hettinger wrote:
It seems like you would get just about everything you want with one line:
once = lru_cache(maxsize=None)
But is it thread-safe?
You can add thread safety the same way as any other function:
@synchronized @once def spam(): return 42 in a slow and non-thread-safe and non-idempotent way and also launch the missiles the second time we’re called
Or wrap a with lock: around the code that calls it, or whatever.
Not all uses of once require thread safety. For the really obvious example, imagine you’re sharing a singleton between coroutines instead of threads. And if people are really concerned with the overhead of lru_cache(maxsize=None), the overhead of locking every time you access the value is probably even less acceptable when unnecessary.
So, I think it makes sense to leave it up to the user (but to explain the issue in the docs). Or maybe we could add a threading.once (and asyncio.once?) as well as functools.once?
_______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/RSJLUF... Code of Conduct: http://python.org/psf/codeofconduct/